This is one I'm not sure how to go about. Basically I have an ASyncTask class thats doing its business as usual in the background. I'd like to do something after its finished. Now before you jump ahead and say "just use onPostExecute()", theres a catch. The method I need run is in the activity and not the Task class.
The way I see it, I have 2 options.
CustomTask task = new CustomTask();
task.execute(passedParams);
//when(task.execute is finished)
{
doX();
}
I hope I can do it this way as Its so simple and lets me check when the task is completed without having to constantly poll it for activity and getStatus() on the activity. I don't think I'll get this lucky but If anyone has a way of doing it, that'd be great
Pass the activity as a paramater to the ASyncTask. This is messy and I'm not happy about using it but asides from that and the object reference, I don't know if it will work
CustomTask task = new CustomTask();
task.execute(passedParams,MyActivity);
Then in the Tasks onPostExecute, I can just have it call the MyActivity.doX();
A third way would be to make the asynctask a private class in the activity itself but i really would like to keep it separate. Resusability and what not –
Any thoughts on this?
To summarize, Need to doX() after task.execute is finished. Any ideas appreciated.
Ok I know I'm on a roll here. I keep thinking up new solutions. A class method or static method that can be called from any where.
public class ProfileSettings extends Activity
{
public static void doX()
{
//Logic...
}
}
From AsyncTask
MyActivity.doX();
Option B should work and is sometimes a good option, but sometimes I use anonymous classes for this. When you call it from your activity:
CustomTask task = new CustomTask() {
@Override
protected void onPostExecute(Long result) {
super.onPostExecute(result);
MyActivity.this.doX();
}
}.execute();
Option A:
Android API has already provided built-in function for this purpose AsyncTask.get():
CustomTask task = new CustomTask();
task.execute(passedParams);
Result result = task.get(); // <- Block UI thread and waiting for AsyncTask finish.
this.doX(result);
As you can see, this is a bad practice as it blocks UI thread and may cause ANR exception, By doing this, you are actually sacrifice the benefit of AsyncTask, and make it running synchronously with UI thread.
Option B and C:
Both are correct way of doing things, by calling doX() method in onPostExecute() method,
AsyncTask, as its name stated, run a background thread asynchronously with UI thread, and once the background thread is finished, onPostExecute method is called on UI thread. There is no way to tell exactly when onPostExecute method is called (i.e. when doInBackground method is finished) at project build time, as it is determined at app run time, the only thing we know is onPostExecute method is guaranteed to be called on UI thread at some point in the future, In another word, when writing code at project build time, we never know exactly when the doInBackground is finished and code execution jump back to UI thread outside onPostExecute method (Unless you implement some waiting mechanism in code like Option A). So the purpose of onPostExecute method is for processing everything after doInBackground method is finish, this is also why the only argument of onPostExecute method is the result returned from doInBackground method.
The difference between Option B and C is whether to implement AsyncTask as inner class or separate class. This has been aksed and discussed many times in StackOverflow. Most people think it is good to separate them for resusability reason or etc. From my point of view, I don't agree with it. Java Programming Language has its reason provide inner class syntax to suit some special coding situations, when talking about code refactoring from a OOP perspective, think more from problem abstraction level, not simply strip inner class out from Activity class at code level. As you can see in your example, by isolating AsyncTask from Activity, you don't gain any real benefit but rather increase the code complexity (need pass activity context reference between classes) to solve problem.
I think you real question is whether or not we should isolate AsyncTask inner class implementation from Activity. For a better OOP code refactoring (reusability, testability and etc.), checkout my answer in this StackOverflow question to see how to isolate business layer from application UI layer properly.
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