In the past I always did AsyncTasks as private inner classes. The tutorials I found still recommend this (see here, here, here, and here). However, this has the potential to leak the context. Now Android Studio even warns about this and recommends making the class static.
I followed this advice. Here is my code for a sample project I made that updates the UI after a long running task finishes. Since the AsyncTask is static, I pass in a weak reference to the Activity and get the particular UI view that I need to update.
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new MyTask(this).execute();
}
private static class MyTask extends AsyncTask<Void, Void, Void> {
private WeakReference<Context> contextReference;
MyTask(Context context) {
contextReference = new WeakReference<>(context);
}
@Override
protected Void doInBackground(Void... params) {
try {
Thread.sleep(2000);
// in the future I will do other long running tasks here,
// like updating a database. I hope it is acceptable to
// to use sleep for now. This was an actual project that
// I made and tested myself.
} catch (InterruptedException e) {
Log.e("TAG", e.toString());
}
return null;
}
@Override
protected void onPostExecute(Void result) {
AppCompatActivity context = (AppCompatActivity) contextReference.get();
if(context != null) {
TextView textView = context.findViewById(R.id.textview);
textView.setText("task finished");
}
}
}
}
Concerns
The above code works fine, even though it is a pain to not just update an Activity member variable directly. Also, since I don't see any tutorials or the documentation showing AsyncTask working like this, I don't know if this is the pattern I should follow from now on.