To keep the user experience (UX) running smoothly, the Android framework provides a helper class called AsyncTask, which processes work off of the UI thread. Using AsyncTask to move intensive processing onto a separate thread means that the UI thread can stay responsive.
- AsyncTask is an abstract class, which means you must subclass it in order to use it
- Params: The data type of the parameters sent to the task upon executing the doInBackground() override method.
- Progress: The data type of the progress units published using the onProgressUpdated() override method.
- Result: The data type of the result delivered by the onPostExecute() override method. Example:
public class MyAsyncTask
extends AsyncTask <String, Integer, Bitmap>{}- Create a new Java class called SimpleAsyncTask that extends AsyncTask and takes three generic type parameters.
public class SimpleAsyncTask extends AsyncTask <Void, Void, String>{}- At the top of the class, define a member variable mTextView of the type WeakReference:
private WeakReference<TextView> mTextView;*What is the weak reference (the WeakReference class) for? If you pass a TextView into the AsyncTask constructor and then store it in a member variable, that reference to the TextView means the Activity cannot ever be garbage collected and thus leaks memory, even if the Activity is destroyed and recreated as in a device configuration change. This is called creating a leaky context, and Android Studio will warn you if you try it. The weak reference prevents the memory leak by allowing the object held by that reference to be garbage collected if necessary.
- Implement a constructor for AsyncTask that takes a TextView as a parameter and creates a new weak reference for that TextView:
SimpleAsyncTask(TextView tv) {
mTextView = new WeakReference<>(tv);
}- Do what we have to do in the doInBackground method.
- get the result of the job in the onPOstExecute method
protected void onPostExecute(String result) {
mTextView.get().setText(result);
}- Because mTextView is a weak reference, you have to deference it with the get() method to get the underlying TextView object, and to call setText() on it.
- When you rotate the device, the system restarts the app, calling onDestroy() and then onCreate(). The AsyncTask will continue running even if the activity is destroyed, but it will lose the ability to report back to the activity's UI. It will never be able to update the TextView that was passed to it, because that particular TextView has also been destroyed.
- Once the activity is destroyed the AsyncTask will continue running to completion in the background, consuming system resources. Eventually, the system will run out of resources, and the AsyncTask will fail.
- Even without the AsyncTask, the rotation of the device resets all of the UI elements to their default state, which for the TextView is the default string that you set in the layout file.
- For these reasons, an AsyncTask is not well suited to tasks which may be interrupted by the destruction of the Activity. In use cases where this is critical you can use a different type of background class called an AsyncTaskLoader which you will learn about in a later practical.