(I'm sorry for not being so clear in my first post)
Here is the situation: I have data that is to be refreshed from the Internet. Let's call it Model
.
What I want to do: Basically it sounds like an MVC model, where the Model
is also kept persistent in local (private) storage. The Model
and its associated methods are application-wise. There are several Activity
's that display and manipulate different aspects of it:
Activity
's
that display Model
from different perspectives. Currently I have a ListActivity
for all elements, and an Activity
for one element's detailsModel
needs refreshing.
Surely this is done on a different thread. Refreshing can be triggered from several Activity
's.Activity
'sModel
to private storage when it starts
and stopsMy problem: I'm not sure where to put Model
and the related tasks in. Also, I don't know what mechanism to use to notify Activity
's. Currently I come up with 2 approaches:
Service
and send broadcasts. Saving to disk is performed in Service#onDestroyed()
, so I want to minimize that by binding it to Activity
's. At this point, I'm also not sure how to deliver the updated information: whether to provide a getter in Binder
, or include that in the broadcast message.Application
object so that refreshing methods and getters are available globally. I then perform update from Activity
's using AsyncTask
. If there are other Activity
's that are behind the current Activity
, they will update in onResume()
when the user navigates back.Reasons I'm not using a class with static methods:
Model
to disk.Also, I don't put these functionalities in an Activity
because there are several activities that manipulate the same piece of persistent data.
Below are pseudocode illustrating what I mean:
Using Service:
/** Service maintaining state and performing background tasks */
class MyService extends Service {
Model mModel;
Binder mBinder;
onCreate() {
super.onCreate();
mBinder = new Binder();
// load mModel from disk, or do default initialization
}
onDestroy() {
super.onDestroy();
// save mModel to disk
}
onBind() {
return mBinder;
}
class Binder {
refresh() {
new AsyncTask() {
doInBackground() {
// update mModel from Internet
}
onPostExecute() {
sendBroadcasts(new Intent("my.package.REFRESHED"));
}
}.execute();
}
getState() {
return mModel.getState();
}
}
}
/** Activity displaying result */
class MyActivity extends ListActivity {
MyService.Binder mBinder;
onCreate() {
super.onCreate();
// register mReceiver
// bind service
}
onDestroy() {
super.onDestroy();
// unbind service
// unregister mReceiver
}
/** Invokes time-consuming update */
refresh() {
// binding is asynchronous, and user may trigger refreshing too early
if (mBinder != null) {
mBinder.refresh();
}
}
BroadcastReceiver mReceiver = new BroadcastReceiver() {
onReceive(Intent intent) {
if ("my.package.REFRESHED".equals(intent.getAction())
&& mBinder != null) {
updateViews(mBinder.getState());
}
}
};
}
Make the functionality globally accessible in the custom Application object
/** Custom Application providing domain specific functionalities */
class MyApplication extends Application {
Model mModel;
onCreate() {
super.onCreate();
// load mModel from disk, or do default initialization
}
onTerminate() {
super.onTerminate();
// save mModel to disk
}
void refresh() {
/** time-consuming */
}
getState() {
return mModel.getState();
}
}
/** Activity displaying result */
class MyActivity extends ListActivity {
onResume() {
super.onResume();
// in case some top Activities have refreshed
// and user is navigating back
updateViews(((MyApplication)getApplicationContext()).getState());
}
/** Invokes time-consuming update */
refresh() {
new AsyncTask() {
doInBackground() {
((MyApplication)getApplicationContext()).refresh();
}
onPostExecute() {
// update the ListView according to result
updateViews(((MyApplication)getApplicationContext()).getState());
}
}.execute();
}
}
Weaknesses I can think of for the Service
approach is complexity, since Binding is asynchronous. And it's very likely that I have to repeat some code because I have both ListActivity
and Activity
For the Application
approach, the documentation says not to rely on onTerminate()
being called.
I know I'm being very awkward. What is the conventional way to solve this sort of problem?
Many thanks.
Service
s are mostly suitable for something that is not bound to a single Activity
(and usually work together with NotificationManager
or a Widget
). This doesn't seem to be the case.
So my suggestion is to have a well-engineered AsyncTask
that manages state via SharedPreferences
/SQLite
itself (instead of abusing Applicaion
) and will be launched from the ListActivity
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With