Share
Introduction
Programming on Android is pretty easy. At least it is at first, then the subtleties creep in -- like maintaining state, long running tasks, managing orientation changes, and so on. When you get to that stuff programming Android gets, well, not hard, but let's say more complicated.AsyncTask Basics
The Android APIs are generally very nice, and there are ways to deal with just about any situation, it's just that they aren't always obvious. In this tutorial we will apply the knowledge we learnt in the article Creating and Using Databases in Android. Here we are going to fill out more details, including adding an android.app.Application object to stash expensive objects and maintain state, adding a few more data operations, and putting said data operations onto a background Thread using AsyncTask (plus demonstrating saving instance state when the screen orientation is changed, and restoring same).The complete application, which is intended to be very simple, will look like the screen shot below:

As you can see this example allows us to enter data, then press "Save," and that data is stored in a database. Also, this example shows the current data from the database, and allows us to clear/delete it.
Again, this is a simplified example that is intended to give you an idea of what the possibilities and related problems with long running tasks are, and an overview of how to use the Application object. For more complete information, as always, see the Android docs (specifically for AsyncTask management stuff, and you might also want to check out Droid-Fu which is an excellent little utility library that helps, and goes much farther than this example, with AsyncTask management).
Ok, so on with our example. The complete code for this project, in case you just want to jump in that way, you can download it at the end of this article.
The first notable code with this update is the Main Activity, as seen below:
1 |
public class Main extends Activity { |
In this code we start with a typical onCreate method that inflates views and includes a Button click listener. But, you might also have noticed we are setting up a "MyApplication" object which is an instance of Application. The android.app.Application object is very useful, for many reasons. You can stick state there and share it between activities (you can do this with getters and setters, simple), and you can use it to instantiate objects that are needed by your app in more than one activity and are relatively expensive to create. The context of the Application object is "lives" as long as your application, and is different from the context of any single activity. For our simple example we only have one activity, but we are using the application object to demonstrate what the possibilities are. To use the application object you need to extend it, and you need to add android:name="[ApplicationClassName] to the "application" element of your manifest. Our "MyApplication" object for this example is shown below:
1 |
public class MyApplication extends Application { |
Real simple. Here we *could* add getters and setters and store state, but basically we are using the longer lifecycle of the application object to create our DataHelper object and make it available to activities. Application let's you do much more than this, but the basics are state and longer life-cycle (see the docs for more info). Even though application is very useful, and very simple, it's often overlooked.
The next significant part of our new Main activity (going back to the previous code snippet above) is that it no longer calls data operations directly. Instead, it uses several inner AsyncTask classes to move these operations OFF of the main UI thread and onto another thread where they can run asynchronously.
This is HUGE. Ok, our sample application doesn't have anything fancy/long running to do, so it's overkill for the purposes of the example here, but in real life these data operations might be a lot more complicated and time consuming. And, you can use AsyncTask for anything, network operations are another common case.
AsyncTask replaces a lot of manual Handler/Thread/wiring that was needed in the original Android SDKs - it's a convenience for you. AsyncTask has an execute method that performs your long running task on a thread SEPARATE from the main UI thread automatically, and has clear pre and post methods where you CAN interact with the main UI thread too. From the example code, where we have 3 AsyncTask instances for our different data operations, the pattern should be clear (another approach might have been to have ONE task here, and to use the execute method arguments to determine the operation -- that would also allow us to manage the task state itself better, but that is getting beyond the scope of this example). One caveat with this example is that we are not properly using onPause (remember I said it was oversimplified). You should always clean up in onPause, and if you use an AsyncTask that shows a ProgressDialog, you'll want to make sure to dismiss it there (if it is showing, else it will leak).
NOTE Overall, the way we are handling the ProgressDialog in the AsyncTasks here is naive. It's better to use an external ProgressDialog and make use of the onProgressUpdate and publishProgress methods. That gives you more control over the dialog, and makes it easier to prevent errors when activities are restarted (orientation changes, for which you still need to use onPause and cleanup).
After the new task code we also have now implemented the onSaveInstanceState and onRestoreInstanceState methods of Activity. These are for instance state only (some call it "transient" state -- that may seem an odd turn of phrase, but this is state only associated with current instance of the activity, not persistent state, for that we are using the database). These allow us to save simple UI state, such as the contents of a text view, or what checkbox is checked, in case the activity is restarted suddenly, in mid course. This wouldn't really be all that important except for the fact that any orientation change does *exactly this* (yes, it restarts your activity and the life-cycle happens again). For this simple example we have only one input field ("input") to worry about, but you can see how this could be applied to any number of elements. And, in fact, this is unnecessary for a TextView because the framework does it for us with it's own onSaveInstanceState method. The trick is that you need to be aware of it and make sure you handle it in cases where it's not automatic (such as your own custom views). If you want to see how this works with a plain TextView, override the onSaveInstanceState method and do nothing, then change the orientation, and any text in the view will be lost.
That does it for this time. Our new AndroidExamples application now has a slightly more useful user interface that allows us to enter and delete data, and displays it all. Additionally we are now using the Application object to create our DataHelper, and our helper performs all of the data management tasks we need (creating the database, and basic CRUD operations). Also, every time we invoke data related methods we are now doing this with AsyncTask instances, so that these operations are not blocking the UI thread. This is still an oversimplified example, of course, and we are really only scratching the surface, but I do hope it might provide some insight as to where you can start to clean up your Android apps and deal with the sticky spots.
Thanks Screaming-Penguin for this article!!!
Comments (8)
-
2011-01-05 15:03:20 |Author| Narendar
-
2011-05-03 14:36:51 |Author| rameshmenan1989
thanq
-
2011-07-25 11:33:54 |Author| Shaista
thanks
-
2012-01-23 12:55:08 |Author| prabin1987
Thanks for very useful info
Only registered users can write comments!








Do we need to add @override for each methods like doInBackground(), onPreExecute() and so on in AsyncTask implemenation ?