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