问题
Is it at all possible, from within an AsyncTask that is NOT an inner class of the calling Activity class, to get a reference to the instance of Activity that initiated execution of the AsyncTask?
I am aware of this thread, however it doesn't exactly address how to reference the calling Activity. Some suggest passing a reference to the Activity as a parameter to the AsyncTask constructor, however, it's reported that doing so will always result in a NullPointerException.
So, I'm at a loss. My AsyncTask provides robust functionality, and I don't want to have to duplicate it as an inner class in every Activity that wants to use it. There must be an elegant solution.
回答1:
The "elegant solution" is to actually try passing it as a parameter (to the constructor or execute()
) and see if it works, rather than assuming the person who asked that previous question (then answered his own question twice) knows what he is doing. I can think of nothing intrinsic to AsyncTask
that would cause Activity
to be a bad constructor parameter and every other object be just fine.
Now, I haven't passed an Activity
(or other Context
) as a parameter to an AsyncTask
, because my AsyncTasks
are always private inner classes. In fact, the fact that you want a public AsyncTask
to me is a code smell, suggesting these tasks should be mediated by a Service
or some other control point. But, that's just me.
UPDATE
A better answer for handling this pattern can be found here: Background task, progress dialog, orientation change - is there any 100% working solution?
回答2:
My AsyncTask
s always live in a separate package while still bound to a particular type of Activity
. They accept it's instance in constructor and store in a local variable.
Try thinking in terms of creating an abstract Activity
class that encapsulates AsyncTask
-related stuff and is extended by other activities.
Like so:
public abstract RemoteListActivity<T> extends ListActivity{
// calls AsyncTask, shows spinning progress dialog, etc
protected abstract T someConcreteMethod();
}
public final class CustomerListActivity extends RemoteListActivity<Customer>{
protected final Customer someConcreteMethod();
}
Alternatively, if things don't fit in a single hierarchy, have an interface:
interface LazyLoadable {
void setLoadingState();
void setDefaultState();
}
public class MyActivity extends Activity implements LazyLoadable{
}
public final class AsyncTask extends AsyncTask<Void, Void, Void>{
private final LazyLoadable lazyLoadable;
public MyAsyncTask(Context ctx, LazyLoadable lazyLoadable){
super(ctx);
this.lazyLoadable = lazyLoadable;
}
}
来源:https://stackoverflow.com/questions/2719433/getting-reference-to-calling-activity-from-asynctask-not-as-an-inner-class