Skip to content

Instantly share code, notes, and snippets.

@MohammadSamandari
Created April 2, 2020 22:25
Show Gist options
  • Save MohammadSamandari/b211ab2d87531ca37fc266c496be1b2a to your computer and use it in GitHub Desktop.
Save MohammadSamandari/b211ab2d87531ca37fc266c496be1b2a to your computer and use it in GitHub Desktop.
AsyncTask

AsyncTask

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

When you create an AsyncTask subclass, you can configure it using these parameters:

  1. Params: The data type of the parameters sent to the task upon executing the doInBackground() override method.
  2. Progress: The data type of the progress units published using the onProgressUpdated() override method.
  3. Result: The data type of the result delivered by the onPostExecute() override method. Example:
public class MyAsyncTask
   extends AsyncTask <String, Integer, Bitmap>{}

AsyncTask Example:

  1. Create a new Java class called SimpleAsyncTask that extends AsyncTask and takes three generic type parameters.
public class SimpleAsyncTask extends AsyncTask <Void, Void, String>{}
  1. 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.

  1. 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);
}
  1. Do what we have to do in the doInBackground method.
  2. 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.

There are several things going on here:

  • 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.
package mohammad.samandari.simpleasynctask;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void sleep (View view) {
TextView textView = findViewById(R.id.textView);
textView.setText("Sleeping Started");
MyAsyncTask myAsyncTask = (MyAsyncTask) new MyAsyncTask(textView).execute();
}
}
package mohammad.samandari.simpleasynctask;
import android.os.AsyncTask;
import android.widget.TextView;
import java.lang.ref.WeakReference;
import java.util.Random;
public class MyAsyncTask extends AsyncTask<Void,Integer,String> {
WeakReference<TextView> mTextView;
public MyAsyncTask(TextView tv){
mTextView = new WeakReference<>(tv);
}
@Override
protected String doInBackground (Void... voids) {
Random r = new Random();
int random = r.nextInt(100);
try {
for (int i = 0; i < random; i++) {
Thread.sleep(1);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Thread Slept For " + random + " Miliseconds";
}
@Override
protected void onPostExecute (String s) {
super.onPostExecute(s);
mTextView.get().setText(s);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment