Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Very simple code, but got error "Activity has been destroyed" when use Fragment

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>
like image 750
Leem.fin Avatar asked Feb 03 '12 16:02

Leem.fin


People also ask

What happens to fragment when activity is destroyed?

As Fragment is embedded inside an Activity, it will be killed when Activity is killed. As contents of activity are first killed, fragment will be destroyed just before activity gets destroyed.

How can I tell if an Android fragment is destroyed?

Since all fragments are destroyed if the activity is destroyed, a simple answer could be calling getActivity(). isDestroyed() returning true if the activity is destroyed, therefore the fragment is destroyed.

Can fragment be created without activity?

Fragment can't be initiated without Activity or FragmentActivity.

Can a fragment contain an activity?

A fragment represents a modular portion of the user interface within an activity. A fragment has its own lifecycle, receives its own input events, and you can add or remove fragments while the containing activity is running. This document describes how to create a fragment and include it in an activity.


4 Answers

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();
}
like image 157
rishabhmhjn Avatar answered Oct 20 '22 00:10

rishabhmhjn


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

like image 29
Leem.fin Avatar answered Oct 20 '22 00:10

Leem.fin


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();
}
like image 38
vikoo Avatar answered Oct 20 '22 00:10

vikoo


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.

like image 30
sstn Avatar answered Oct 19 '22 23:10

sstn