General application design (IntentService/ContentProvider/AsyncTask)
I'm trying to figure out what is the best general design for applications that access several web services and have multiple activities where information is displayed.
The way I implemented my latest Android application is the following. I have an IntentService that receives requests from activities to get information from web services. My Service notifies the activities through a ResultReceiver about the status of the request (started/error/finished). After calling the web service, getting the result(xml/json) and parsing it, I put that information in a ContentProvider (backed up by a sqlite database) and use a ContentResolver to notify any activities about the changes. The activities get notified about the changes (some use ContentObserver and others use SimpleCursorAdapters and are notified automatically).
Now, the problems with my approach:
- every time I enter an activity, I request info from web service through the method described above and I delete all the rows in that particular table, fill it with the new info and notify the activity. So, if the user presses back and then enters again, I do the whole dance again. I think I should add some fields in the database for when was the last updated etc. but I don't know how exactly to proceed with that. Suggestions? I think one alternative would be to use alarms and trigger updates at specific intervals. But in my case, the specification asks to check the web service every time I enter the activity.
- when I call the web service, I show a indeterminate progress bar in the activity, over the other views (which contain the info fetched previously and that sits in the database until the web service call finishes) but the user can start interacting with the views and this is not good (the info may disappear from the database). Any way to disable the interaction? A ProgressDialog comes to mind.
- if I move quickly through different activities, the IntentService is blocked with previous web service calls and it takes longer to get to my latest web service call. I could create multiple IntentService for every web service but I don't think this is its purpose.
I have the feeling that the approach I have taken is not really the best one for this particular application. It is partially inspired from the Google I/O application (I couldn't understand everything, like the updated sqlite fields etc.). One alternative would have been to use AsyncTasks in all the activities. But where can I store the info in order to be accessed from other activities? In lists in Application? And how about id management?
I'm really interested on your opinions/ideas/suggestions and how can I make my next applications work better and more efficiently.
Did you check this talk? http://www.youtube.com/watch?v=xHXn3Kg2IQE
I found it a source of good inspiration. Basically, they suggest to build a service helper (in your case, a service helper to your intent service) as a singleton class. You can track the ongoing requests
In this way you can track every different kind of ongoing background tasks you are performing, and block any other request of the same kind. For example, if you leave activity a and enter activity b, and they ask for the same web service query, you can check that it is still in progress because of activity a.
From what I saw on iosched app, it suffers of the problem that if the activity was closed, the fetch result gets lost.
There is a clear log that says:
Log.w(TAG, "Dropping result on floor for code " + resultCode + ": " + resultData.toString());
I don't suggest using asynctask too, because the result would be lost as well.
However, take a look at the talk and to the slides.