java.lang.IllegalStateException: FragmentManager 已销毁

java.lang.IllegalStateException: FragmentManager has been destroyed

在 activity onResume 方法中,我调用了 volley 请求,它正在获取项目列表,然后将它们加载到此 activity 中的 ListFragment。当我第一次输入 activity 时,一切正常,但当我重新输入 activity 时,ListFragment 为空,并且控制台中有消息 "FragmentManager has been destroyed".

这是我的 activity 的代码:

@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();
}

commit()语句抛出异常

我的 ListFragment 代码:

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);
    }
}

据我所知,FragmentManager 在 activity 被销毁时被销毁,但是如何为重新创建的 activity 获取新的 FragmentManager?为什么 getSupportFragmentManager() 不起作用?

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

我想这才是理想的称呼方式。您可以检查一次。

您需要检查 activity 是否仍在 运行 或已经完成

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

 }

该函数将从 activity 生命周期函数中获取布尔值。我认为这对你有用!

我完全不明白为什么它会起作用,但我已经解决了这个问题。我已经创建了静态 activity 变量并在 onCreate 方法中用它启动它:

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

而且我注意到在方法 albumsFoundViewUpdate this.isDestroyed() returns true(当我第二次重新启动此 activity 时)和 activity.isDestroyed() returns假的。所以我像这样重制了 albumsFoundViewUpdate:

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();
}

现在每次都运行良好!

检查与 Volley 请求相关的 class 是否包含对您的 activity 的引用。 如果是这种情况,当您重新启动您的应用程序时,旧的 activity 将被销毁,但请求会向它提供回调,从而导致错误 - “FragmentManager 已被销毁”。 最好在调用 volley 请求函数时将你的 activity 作为回调参考传递,并在对请求回调采取行动之前检查 isFinishing() 。

当您从一个被摧毁的 Activity 中获得 FragmentManager 时,通常会发生这种情况,例如,如果您从另一个 class 中获得 activity.getSupportFragmentManager();

在你的情况下,首先检查 FragmentManager 是否未被销毁,然后使用它:

FragmentManager fragmentManager = getSupportFragmentManager();

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