It is quite common to spawn a time consuming computation thread. Later, we require to update Activity or Fragment with computation result.
All the while, I'm following the below guidelines. It works well for me till now.
setRetainInstance(true) UI-less fragment.setTargetFragment and getTargetFragment techniquesetRetainInstance(true) UI-less fragment.onAttach and onDetach to store reference to Activity. Google seems doesn't encourage using getActivity. http://developer.android.com/guide/components/fragments.html
However, how about case for a class derived from View? I plan to launch AsyncTask from the custom View. However, how can I onPostExecute back to the View?
The reason I'm asking so is, in my custom view, certain touch event will trigger it to redraw itself with a new bitmap. Generating the new bitmap is time consuming. Hence, I plan to launch a AsyncTask, to generate such bitmap, and pass back to custom View. However, configuration change might cause custom View to be recreated. Hence, I need to ensure my AsyncTask can have correct View reference during onPostExecute.
Generally it is convenient to use AsyncTask when you must "skip back" to UI thread when the background task is done or when you have to give some feedback to UI thread during task execution. Otherwise it's just overhead. You are not forced to use AsyncTask.
Android App Development for Beginners Android AsyncTask going to do background operation on background thread and update on main thread. In android we cant directly touch background thread to main thread in android development. asynctask help us to make communication between background thread to main thread.
To start an AsyncTask the following snippet must be present in the MainActivity class : MyTask myTask = new MyTask(); myTask. execute(); In the above snippet we've used a sample classname that extends AsyncTask and execute method is used to start the background thread.
execute(); ... public class asyncextends AsyncTask<Void, Void, String> { protected String doInBackground(Void... progress) { ... } protected void onPreExecute() { ... } protected void onPostExecute(String result) { ... } } }
Assuming that you're using AsyncTask only for drawing-related operations (otherwise you should really revisit your logic - as comments suggest), you can create AsyncTask directly in your custom View class:
class MyView extends View {
private MyAsyncTask currentTask = null;
// View details
@Override
public void onAttachedToWindow() {
currentTask = new MyAsyncTask(this);
currentTask.execute();
}
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (currentTask != null) {
currentTask.cancel(true);
currentTask = null;
}
}
static class MyAsyncTask extends AsyncTask<Void, Void, Bitmap> {
private WeakReference<MyView> viewRef;
MyAsyncTask(MyView view) {
viewRef = new WeakReference<>(view);
}
// background task implementation
@Override
public void onPostExecute(Bitmap bitmap) {
MyView view = viewRef.get();
if (view == null) {
return;
}
// you now can safely update your view - we're on UI thread
}
}
}
That's how safe implementation would look like. It has some disadvantages and important parts:
AsyncTask should hold strong reference to View (that's why class is declared as static and holds WeakReference to View)AsyncTask anymore - cancel itAsyncTask. If that's the issue - I would suggest to remove AsyncTask from View completely and search for others solutions (separate Executor or HandlerThread).Also onPostExecute of AsyncTask will be called from the same looper thread which launched it (in your case that's main thread, so it does not matter if you start it from Activity or View, or wherever else, it all depends on how hard it would be to manage those tasks).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With