(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:
- User
navigates across different
Activity
's that displayModel
from different perspectives. Currently I have aListActivity
for all elements, and anActivity
for one element's details - Sometimes
Model
needs refreshing. Surely this is done on a different thread. Refreshing can be triggered from severalActivity
's. - There are several (time consuming) common
tasks that can be triggered from different
Activity
's - My application loads and saves
Model
to private storage when it starts and stops
My 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:
- Use
Service
and send broadcasts. Saving to disk is performed inService#onDestroyed()
, so I want to minimize that by binding it toActivity
's. At this point, I'm also not sure how to deliver the updated information: whether to provide a getter inBinder
, or include that in the broadcast message. - Customize the
Application
object so that refreshing methods and getters are available globally. I then perform update fromActivity
's usingAsyncTask
. If there are otherActivity
's that are behind the currentActivity
, they will update inonResume()
when the user navigates back.
Reasons I'm not using a class with static methods:
- I need to save and store
Model
to disk. - Some of the methods need a Context for displaying toasts, notifications, caching, etc.
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.