Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

fragments, when am i "active"?

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();
}
like image 971
Jeffrey Blattman Avatar asked Oct 21 '22 16:10

Jeffrey Blattman


2 Answers

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.

like image 136
nhaarman Avatar answered Oct 27 '22 09:10

nhaarman


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 Loaders, 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.

like image 36
Jeffrey Blattman Avatar answered Oct 27 '22 10:10

Jeffrey Blattman