非常简单的代码,但是在使用 Fragment 时出现错误“活动已被破坏”

Posted

技术标签:

【中文标题】非常简单的代码,但是在使用 Fragment 时出现错误“活动已被破坏”【英文标题】:Very simple code, but got error "Activity has been destroyed" when use Fragment 【发布时间】:2012-02-26 06:29:06 【问题描述】:

我制作了一个非常简单的 Activity,它显示了一个简单的 ListFragment,如下所示:

我的活动:

public class MyActivity extends FragmentActivity 

    @Override
    public void onCreate(Bundle savedInstanceState) 
          FragmentManager fragMgr = getSupportFragmentManager();

          FirstFragment list = new FirstFragment();
          fragMgr.beginTransaction().add(android.R.id.content, list).commit();
    


我的 ListFragment:

public class FirstFragment extends ListFragment

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
        inflater.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
        View view = inflater.inflate(R.layout.main, null);
        return view;
    


    @Override
    public void onActivityCreated(Bundle savedInstanceState) 
        super.onActivityCreated(savedInstanceState);

        String listContent[] = "Larry", "Moe", "Curly"; 
        setListAdapter(new ArrayAdapter<String>(getActivity(), R.layout.list_item, listContent));
    
   ...

当我启动我的应用时,我收到了错误消息

 java.lang.IllegalStateException: Activity has been destroyed
E/AndroidRuntime(  947):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2496)
E/AndroidRuntime(  947):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512)
E/AndroidRuntime(  947):    at android.app.ActivityThread.access$2200(ActivityThread.java:119)
E/AndroidRuntime(  947):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863)
E/AndroidRuntime(  947):    at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(  947):    at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime(  947):    at android.app.ActivityThread.main(ActivityThread.java:4363)
E/AndroidRuntime(  947):    at java.lang.reflect.Method.invokeNative(Native Method)
...

它抱怨Activity已被销毁为什么???

附: main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_
  android:layout_
  android:paddingLeft="8dp"
  android:paddingRight="8dp">

  <Button
    android:layout_
    android:layout_
    android:text="next" />

  <ListView
    android:id="@android:id/list"
    android:layout_
    android:layout_
    android:background="#00FF00"
    android:layout_weight="1"
    android:drawSelectorOnTop="false" />

  <TextView
    android:id="@android:id/empty"
    android:layout_
    android:layout_
    android:background="#FF0000"
    android:text="No data" />
</LinearLayout>

【问题讨论】:

【参考方案1】:

super.onCreate(savedInstanceState)会调用FragmentActivity中的onCreate方法,会调用mFragments.attachHost(null /*parent*/);

这句话会给FragmentController中的mHost赋值,当你调用FragmentTransaction.commit()时,

enqueueAction()方法中,有这句话

 if (mDestroyed || mHost == null) 
        throw new IllegalStateException("Activity has been destroyed");
 

所以如果你在提交 fragmentTransaction 之前没有调用 super.onCreate(savedInstanceState),你会得到这个异常,因为 mHost 为 null

【讨论】:

【参考方案2】:

仍然很糟糕,因为出现错误“活动已被销毁”

ava.lang.IllegalStateException: Activity has been destroyed fragmentTransaction.commitAllowingStateLoss();

所以我的解决方案是添加检查if (!isFinishing()&amp;&amp;!isDestroyed())

 if (!isFinishing()&&!isDestroyed()) 
                        fragmentTransaction.commitAllowingStateLoss();
                    
                

【讨论】:

【参考方案3】:

如果有人遇到类似的问题:

我遇到了同样的问题,但在我的情况下,我是从 Main Activity 调用 Fragment1,然后如果用户单击 Fragment1 布局,我想启动另一个 Fragment2 布局。

我能够从 Main Activity 启动 Fragment1,但从 Fragment1 到 Fragment2 它失败,异常为 "Activity has been destroy"

我通过在 MainActivity 类中将 FragmentManager 对象保持为静态来解决上述问题。 私有静态 FragmentManager mfragmentManager = null;

使用上述相同的对象调用两个片段,解决了我的问题。

下面是我在 Main Activity 中的 Fragment 切换代码。

public void switchToFragment(String fragmentName)
        Fragment fragment = null;
        switch (fragmentName) 
            case "Fragment1":
                fragment = new Fragment1();
                break;
            
            case "Fragment2": 
                fragment = new Fragment2();
                break;
            
        

        FragmentTransaction transaction = mfragmentManager.beginTransaction();
        transaction.replace(R.id.fragment_container, fragment);
        transaction.commit();
    

【讨论】:

【参考方案4】:

我遇到了同样的问题,无法解决。 事件我也添加了 isFinishing() 检查。但没有运气。

然后我又添加了一个检查 isDestroyed() 并且它现在可以正常工作了。

if (!isFinishing() && !isDestroyed()) 
  FragmentTransaction ft = getSupportFragmentManager()
     .beginTransaction();
  ft.replace(LAYOUT_ID, myFragmentInstance);
  ft.commit();

【讨论】:

请注意,onDestroyed() 是在 API 级别 17 中添加的。【参考方案5】:

我所做的是在提交后立即调用

fragmentManager.executePendingTransactions();

并且在调用onpause() 之后永远不要尝试提交

阅读这篇文章Fragment Transactions & Activity State Loss

【讨论】:

【参考方案6】:

我也遇到过类似的问题。 我意识到这是因为活动在FragmentTransaction 即将获得.commit() 时被破坏。

对此的解决方案是检查Activity.isFinishing() 是否为真。

if (!isFinishing()) 
  FragmentTransaction ft = getSupportFragmentManager()
     .beginTransaction();
  ft.replace(SOME_RES_ID, myFragmentInstance);
  ft.commit();

【讨论】:

感谢它对我有用!通过discussion over Github 来到这里。感谢分享。【参考方案7】:

解释一下:

框架创建Activity 并调用Activity.onCreate()

Activity.onCreate() 会以某种方式附加到FragmentManager 以告知其托管活动。 Activity.onDestroy() 将再次取消注册。

现在,您扩展 Activity 并覆盖 onCreate()。您拨打FragmentManager 而不拨打Activity.onCreate()。上面解释的整个注册逻辑没有被执行。 FragmentManager 因此对活动一无所知,并假定它已被销毁并生成带有误导性错误消息的异常。

【讨论】:

【参考方案8】:

为了确保我没看错,MyActivity 是您尝试启动然后添加 FirstFragment 实例的活动,对吗?

我立刻看到了两件你需要看的东西

1) 在您的活动中,您永远不会调用 setContentView() 或 super.onCreate()。第一次调用对您来说可能是个大问题,因为这意味着您的布局从未膨胀,因此 R 变量不存在

2) 您的 MyActivity 需要有自己的 xml 布局文件,而它没有。

【讨论】:

嗨,我不认为一个 Activity 必须有一个布局文件,例如,我的代码在我添加 super.onCreate(...) 后工作,我的 Activity 只是托管一个 Fragment,并且Fragment 将膨胀一个布局来显示,而不是 Activity。 这是可能的,因为我没有真正使用过支持包。我的大部分开发都是在使用多窗格布局的 Honeycomb 上进行的。我只是在查看 API 文档,我认为您是对的。感谢您指出这一点! 没问题,我也是刚接触support包,从今天开始学习fragment :)【参考方案9】:

我自己想通了,这是因为我在我的 Activity onCreate() 方法中错过了super.onCreate(savedInstanceState);。添加后,一切都很好。

【讨论】:

如果有人能解释深层原因,我会接受更好的不是我的:) 就我而言,我正在调用 super.onCreate(savedInstanceState);添加片段后。 @lemm.fin 我正在阅读这篇文章,发现那里的解释很好。 medium.com/@elye.project/…

以上是关于非常简单的代码,但是在使用 Fragment 时出现错误“活动已被破坏”的主要内容,如果未能解决你的问题,请参考以下文章

Android 在Fragment中执行onActivityResult不被调用的简单解决方法

过时的PreferenceActivity导致Fragment显示问题

两层fragment嵌套时出现空白,(收藏别人的)

使用Fragment时如何获取控件Id以及如何跳转

Android Jetpack ------ ViewModel基本使用

Android Jetpack ------ ViewModel基本使用