非常简单的代码,但得到错误"活动已被破坏"什么时候使用片段

时间:2012-02-03 16:32:51

标签: android android-layout android-emulator android-intent android-widget

我做了一个非常简单的活动,它显示了一个简单的 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)
...

它抱怨活动已被破坏为什么???

P.S。 main.xml中:

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

  <Button
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="next" />

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

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

9 个答案:

答案 0 :(得分:67)

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

解决方法是检查Activity.isFinishing()是否为真。

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

答案 1 :(得分:32)

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

答案 2 :(得分:12)

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

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

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

答案 3 :(得分:4)

作出解释:

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

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

现在,您展开Activity并覆盖onCreate()。您拨打FragmentManager电话时无需致电Activity.onCreate()。不执行上面解释的整个注册逻辑。 FragmentManager因此对活动一无所知,并假设它已被销毁,并产生具有误导性错误消息的异常。

答案 4 :(得分:2)

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

我立即看到了你需要看的两件事

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

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

答案 5 :(得分:1)

我所做的就是在提交后立即致电

fragmentManager.executePendingTransactions();

并且永远不会在onpause()调用

之后尝试提交

阅读此Artical Fragment Transactions & Activity State Loss

答案 6 :(得分:1)

还不错,因为得到错误“活动已被破坏”

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

所以我的解决方案是添加支票if (!isFinishing()&&!isDestroyed())

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

答案 7 :(得分:0)

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

当您调用FragmentTransaction.commit()时,此句子将在FragmentController中为mHost赋值;

在方法enqueueAction()中,它有这句话

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

因此,如果在提交fragmentTransaction之前没有调用super.onCreate(savedInstanceState),则会出现此异常,因为mHost为null

答案 8 :(得分:0)

如果有人遇到类似问题:

我正面临同样的问题,但在我的案例中,我从主要活动调用Fragment1然后如果用户点击Fragment1 Layout我想启动另一个Fragment2布局。

我能够从Main活动启动Fragment1但是Fragment1启动Fragment2失败,因为&#34;活动已被销毁&#34;

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

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

以下是来自Main Activity的片段切换代码。

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