22

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 5

19

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();
}
Sign up to request clarification or add additional context in comments.

3 Comments

What should be pass in fragment?
What would be a good practice to write in an "else" block? I mean, when this "if" statement is not executed, what would happen? I should rebuild the activity or the fragment manager?
@iatharva The fragment that you want to show.
8

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!

2 Comments

Where does isFinished comes from ?
thanks for your answer. it was isFinishing() in my case from Activity.java
1
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.

2 Comments

Tried this one, but result is the same. When I call getSupportFragmentManager() for the second time the fragmentManager.isDestroyed() is already = true. I've even tried to create FragmentService class like this public class FragmentService { public static void replaceFragment(FragmentActivity activity, int container, Fragment f){ FragmentManager fragmentManager = activity.getSupportFragmentManager(); fragmentManager.beginTransaction().replace(container, f).commit(); } } but it didn't help either
This is excatly the same like in the question. A temporary variable for the fragment manager changes nothing.
1

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.

Comments

-5

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!

7 Comments

If anyone can explain that, please do. I totally don't get it...
This worked for me as well. I guess it has to do because of the Activity's instance.
please do not add a static reference to an Activity, that will create a memory leak since the reference will never be garbage collected. Try to rotate your device some times and you will have several instances of your Activity in memory
Avoid static instance.. it will create more problems than solve it
@DanielCettour This is the way it has to be. Activities in the background have to be destroyed after some time. Everything you do against this is wrong. If you need a background application you have to create a service.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.