Very simple code, but got error “Activity has been

2019-01-17 21:42发布

问题:

I made a very simple Activity which shows a simple ListFragment like below:

My Activity:

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

}

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

When I start my app, I got error message:

 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)
...

It complains that Activity has been destroyed, Why???

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>

回答1:

I also faced a similar problem.
I realized that this happened because the activity was being destroyed while the FragmentTransaction was about to get .commit().

A solution to this was to check whether the Activity.isFinishing() is true or not.

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


回答2:

I figured out myself, It is because I missed the super.onCreate(savedInstanceState); in my Activity onCreate() method . After added this, things are fine.



回答3:

I faced the same issue and unable to fix it. Event I added isFinishing() check as well. but no luck.

then I added one more check isDestroyed() and its working fine now.

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


回答4:

To give an explanation:

The framework creates the Activity and calls Activity.onCreate().

Activity.onCreate() will somehow attach to the FragmentManager to let it know about the hosting activity. Activity.onDestroy() will unregister it again.

Now, you extend Activity and override onCreate(). You make calls to FragmentManager without calling through toActivity.onCreate(). The whole registration logic explained above is not executed. The FragmentManager therefore does not know anything about the activity and assumes it has already been destroyed and generates the exception with the misleading error message.



回答5:

Just to make sure I'm seeing this right, MyActivity is the activity that you're trying to launch and then add an instance of FirstFragment into, right?

Immediately I see two things that you need to look at

1) In your activity you never call setContentView() or super.onCreate(). The first call could be a huge issue for you because that means that your layout was never inflated, and therefore, the R variable doesn't exist

2) Your MyActivity needs to have its own xml layout file, which it doesn't have.



回答6:

what i did is immediately after commit i call

fragmentManager.executePendingTransactions();

and never try to commit after onpause() called

Read this Artical Fragment Transactions & Activity State Loss



回答7:

Still bad, because got error “Activity has been destroyed”

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

So my solution is add check if (!isFinishing()&&!isDestroyed())

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


回答8:

If any one come across similar type of issue:

I was facing same time of issue, but in my case from Main Activity I was calling to Fragment1 and then if user click on Fragment1 Layout I want to launch another Fragment2 Layout.

I was able to launch Fragment1 from Main activity but Fragment1 to Fragment2 it was failing with exception as "Activity has been destroyed" .

I resolved above issue by maintaining FragmentManager object as static in MainActivity class. private static FragmentManager mfragmentManager = null;

calling to both fragment using same above object, resolved my issue.

Below is my Fragment switching code from 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();
    }


回答9:

super.onCreate(savedInstanceState) will call onCreate method in FragmentActivity, which will call mFragments.attachHost(null /*parent*/);

This sentence will assign a value to mHost in FragmentController, when you calls FragmentTransaction.commit() ,

In the method enqueueAction(),it has this sentences

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

So if you haven't call super.onCreate(savedInstanceState) before you commit a fragmentTransaction, you will get this exception because mHost is null