Reputation: 22637
i've been constantly frustrated by this and i can't find a good answer, so hoping someone here can offer guidance.
i have a fragment that uses AsyncTask
quite extensively. i'm constantly plagued by bugs where the fragment calls getActivity()
, which returns null. i assume these are happening because some method in the fragment are invoked before the activity is attached, or after it is detached.
what's the correct way to handle this in my code? i don't want to have this idiom littered all over the place,
Activity activity = getActivity();
if (activity != null) { // do something }
looking at the docs for Fragment
, i can come up with many possible hooks to solve this: isDetached()
, onActivityCreated()
, onAttach()
, isResumed()
, and so on. what is the right combination?
EDIT:
A few people have suggested canceling tasks when paused, but this implies that the standard idiom,
new AsyncTask<...>.execute();
cannot be used. It implies that every exec'd AsyncTask
needs to be tracked to completion, or canceled. I have simply never seen that in example code from Google or elsewhere. Something like,
private final Set<AsyncTask<?>> tasks = new HashSet<>;
...
AsyncTask<?> t = new AsyncTask<...>() {
...
public void onPostExecute(...) {
tasks.remove(this);
...
}
}
tasks.add(t);
t.execute();
...
@Override
public void onPause() {
for (AsyncTask<?> t: tasks) {
t.cancel();
}
tasks.clear();
}
Upvotes: 5
Views: 5727
Reputation: 22637
I could not find a good solution. In summary, either use a Loader
, or check that getActivity()
does not return null before using it. I looked into using Loader
s, but the pattern makes a lot of assumptions about the structure of the app and the nature of data retrieval that didn't work for me.
Upvotes: 1
Reputation: 7663
In terms of coordinating lifecycles, I keep onActivityCreated
as a mental benchmark - it marks the point at which the underlying activity has finished its own onCreate
. Prior to that I do not believe there is an activity to getActivity()
from.
That get activity is returning null sounds like either you're calling getActivity() too early (i.e. before it is created) or too late (i.e. when it stopped interacting with the fragment). Stopping your tasks in onPause()
would prevent getActivity from returning null since it would cut off the task once the fragment stopped interacting with the underlying activity becuase the activity itself was paused. I think waiting for onStop()
may be too late since, if the task were to still be running when the underlying activity paused it may still reutrn null.
Upvotes: 0
Reputation: 100448
Try to cancel your AsyncTasks in the onPause
or onStop
methods. That will prevent the onPostExecute
from being called when the Fragment
is not active anymore (getActivity()
returns null
).
Or you could check if the Fragment
is attached by calling this.isAdded()
in your Fragment
.
Upvotes: 2