java.lang.IllegalStateException: FragmentManager 已被销毁

Posted

技术标签:

【中文标题】java.lang.IllegalStateException: FragmentManager 已被销毁【英文标题】:java.lang.IllegalStateException: FragmentManager has been destroyed 【发布时间】:2020-06-23 17:49:18 【问题描述】:

在活动onResume 方法中,我调用了 volley request,它获取项目列表,然后将它们加载到此活动中的 ListFragment。当我第一次进入活动时,一切正常,但是当我重新进入活动时,ListFragment 是空的,并且控制台中有消息“FragmentManager 已被销毁”。

这是我的活动代码:

@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() 不起作用?

【问题讨论】:

【参考方案1】:

您需要检查活动是否仍在运行或已完成

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

 

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

【讨论】:

isFinished 从何而来?【参考方案2】:

当您从已销毁的 Activity 中获取 FragmentManager 时会发生这种情况,例如,通常是在您从另一个类中获取 activity.getSupportFragmentManager(); 时。

在你的情况下,首先检查FragmentManager是否没有被破坏,然后使用它:

FragmentManager fragmentManager = getSupportFragmentManager();

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

【讨论】:

【参考方案3】:
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
    .replace(R.id.artist_activity__albums_container, fragment)
    .commit();

我想理想情况下应该这样称呼它。您可以检查一次。

【讨论】:

试过这个,但结果是一样的。当我第二次调用 getSupportFragmentManager() 时,fragmentManager.isDestroyed() 已经 = true。我什至尝试过创建这样的 FragmentService 类 public class FragmentService public static void replaceFragment(FragmentActivity activity, int container, Fragment f) FragmentManager fragmentManager = activity.getSupportFragmentManager(); fragmentManager.beginTransaction().replace(container, f).commit(); 但它也没有帮助【参考方案4】:

检查与 Volley 请求相关的类是否包含对您的活动的引用。 如果是这种情况,当您重新启动应用程序时,旧的活动将被破坏,但请求会向它提供回调,这会导致错误 - “FragmentManager 已被破坏”。 最好在调用 volley 请求函数并检查 isFinishing() 时将您的活动作为回调引用传递,然后再对请求回调进行操作。

【讨论】:

【参考方案5】:

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

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

我注意到,在方法 albumsFoundViewUpdate this.isDestroyed() 返回 true(当我第二次重新启动此活动时)并且 activity.isDestroyed() 返回 false。所以我重新制作了 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();

现在每次都能正常工作!

【讨论】:

如果有人能解释一下,请做。我完全不明白... 这对我也有用。我想它必须这样做是因为 Activity 的实例。 请不要向 Activity 添加静态引用,这会造成内存泄漏,因为引用永远不会被垃圾回收。尝试旋转您的设备几次,您将在内存中拥有多个 Activity 实例 避免静态实例..它会产生比解决它更多的问题

以上是关于java.lang.IllegalStateException: FragmentManager 已被销毁的主要内容,如果未能解决你的问题,请参考以下文章