java.lang.IllegalStateException: FragmentManager has been destroyed

Viewed 12242

In activity onResume method I call volley request, which is getting list of items and then loads them to ListFragment inside this activity. When I enter activity for the first time everything is working correctly, but when I re-enter activity the ListFragment is empty and there is message in console "FragmentManager has been destroyed".

This is my activity's code:

@Override
protected void onResume() {
    super.onResume();
    // Volley request inside - which call back albumsFoundViewUpdate
    artistController.getArtistAlbums(artist);
}

public void albumsFoundViewUpdate(ArrayList<UserAlbumLink> links)
{
    // Load list fragment
    UserAlbumLinkListFragment fragment = new UserAlbumLinkListFragment(links, artist);
    getSupportFragmentManager().beginTransaction().replace(R.id.artist_activity__albums_container, fragment).commit();
}

The exception is thrown at commit() statement.

My ListFragment code:

public class UserAlbumLinkListFragment extends ListFragment {
    private List<UserAlbumLink> albumLinks;
    private UserAlbumLinkListAdapter adapter;
    private Artist artist;


    public UserAlbumLinkListFragment() {
    }

    public UserAlbumLinkListFragment(List<UserAlbumLink> albumLinks, Artist artist) {
        this.albumLinks = albumLinks;
        this.artist = artist;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        adapter = new UserAlbumLinkListAdapter(getActivity(), R.layout.album_list_item, albumLinks, artist);
        setListAdapter(adapter);
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_album_list, container, false);
    }
}

As I understand FragmentManager gets destroyed when activity is getting destroyed, but how do I get new FragmentManager for recreated activity? Why getSupportFragmentManager() is not working?

5 Answers

This happens when you get the FragmentManager from an Activity that was destroyed, usually if you do activity.getSupportFragmentManager(); from another class for example.

In your case, first check if the FragmentManager was not destroyed, then use it:

FragmentManager fragmentManager = getSupportFragmentManager();

if (!fragmentManager.isDestroyed()) {
    fragmentManager
    .beginTransaction()
    .replace(R.id.artist_activity__albums_container, fragment)
    .commit();
}

you need to check whether the activity is still running or it has finished

if(!isFinished()){
 FragmentManager fragmentManager = getSupportFragmentManager();
 fragmentManager.beginTransaction()
.replace(R.id.artist_activity__albums_container, fragment)
.commit();

 }

that function will get the boolean value from activity lifecycle functions. I think this will work for you!

FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
    .replace(R.id.artist_activity__albums_container, fragment)
    .commit();

I guess this is how it should ideally be called. You may check once.

Check if the class related to Volley request is holding a reference to your activity. If that is the case, by the time you relaunch your application, the old activity would have been destroyed but the request gives the callback to it which leads to the error - "FragmentManager has been destroyed". It is better to pass your activity as callback reference while calling the volley request functions and checking isFinishing() before acting on the request callback.

I totally didn't get why did it worked, but I've solved the problem. I've created static activity variable and initiate it with this in onCreate method:

private static ArtistActivity activity;
@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    activity = this;
    ...
}

And I've noticed that in method albumsFoundViewUpdate this.isDestroyed() returns true (when I relaunch this activity for second time) and activity.isDestroyed() returns false. So I've remake albumsFoundViewUpdate like this:

public void albumsFoundViewUpdate(ArrayList<UserAlbumLink> links)
{
    // Load list fragment
    UserAlbumLinkListFragment fragment = new UserAlbumLinkListFragment(links, artist);
    FragmentManager fragmentManager = activity.getSupportFragmentManager();
    fragmentManager.beginTransaction().replace(R.id.artist_activity__albums_container, fragment).commit();
}

and now it's working perfectly fine every time!

Related