webentwicklung-frage-antwort-db.com.de

java.lang.IllegalStateException: Diese Aktion kann nach onSaveInstanceState nicht ausgeführt werden

Ich verwende die Support-Bibliothek für meine App. In meiner FragmentActivity verwende ich eine AsyncTask zum Herunterladen von Daten aus dem Internet. In der onPreExecute () - Methode füge ich ein Fragment hinzu und in der onPostExecute () - Methode entferne ich es wieder. Wenn die Ausrichtung zwischendurch geändert wird, erhalte ich die oben erwähnte Ausnahme. Bitte sehen Sie sich die Details an:

private class onFriendAddedAsyncTask extends AsyncTask<String, Void, String> {
    DummyFragment dummyFragment; 
    FragmentManager fm;
    FragmentTransaction ft;

@Override
protected void onPreExecute() {
    Log.v("MyFragmentActivity", "onFriendAddedAsyncTask/onPreExecute");
    dummyFragment = DummyFragment.newInstance();
    fm = getSupportFragmentManager();
    ft = fm.beginTransaction();
    ft.add(dummyFragment, "dummy_fragment");
    ft.commit();
}

@Override
protected void onPostExecute(String result) {
    Log.v("MyFragmentActivity", "onFriendAddedAsyncTask/onPostExecute");
    ft = fm.beginTransaction();
    ft.remove(dummyFragment);
    ft.commit();
}

@Override
protected String doInBackground(String... name) {
    Log.v("MyFragmentActivity", "onFriendAddedAsyncTask/doInBackground");
    ...
}

Ich bekomme folgendes LogCut:

01-05 23:54:19.958: V/MyFragmentActivity(12783): onFriendAddedAsyncTask/onPreExecute
01-05 23:54:19.968: V/DummyFragment(12783): onAttach
01-05 23:54:19.968: V/DummyFragment(12783): onCreate
01-05 23:54:19.968: V/MyFragmentActivity(12783): onFriendAddedAsyncTask/doInBackground
01-05 23:54:19.973: V/DummyFragment(12783): onCreateView
01-05 23:54:19.973: V/DummyFragment(12783): onActivityCreated
01-05 23:54:19.973: V/DummyFragment(12783): onStart
01-05 23:54:19.973: V/DummyFragment(12783): onResume
01-05 23:54:21.933: V/MyFragmentActivity(12783): onSaveInstanceState
01-05 23:54:21.933: V/DummyFragment(12783): onSaveInstanceState
01-05 23:54:21.933: V/MyFragmentActivity(12783): onPause
01-05 23:54:21.933: V/DummyFragment(12783): onPause
01-05 23:54:21.938: V/MyFragmentActivity(12783): onStop
01-05 23:54:21.938: V/DummyFragment(12783): onStop
01-05 23:54:21.938: V/MyFragmentActivity(12783): onDestroy
01-05 23:54:21.938: V/DummyFragment(12783): onDestroyView
01-05 23:54:21.938: V/DummyFragment(12783): onDestroy
01-05 23:54:21.938: V/DummyFragment(12783): onDetach
01-05 23:54:21.978: V/MyFragmentActivity(12783): onCreate
01-05 23:54:21.978: V/DummyFragment(12783): onAttach
01-05 23:54:21.978: V/DummyFragment(12783): onCreate
01-05 23:54:22.263: V/MyFragmentActivity(12783): onStart
01-05 23:54:22.313: V/DummyFragment(12783): onCreateView
01-05 23:54:22.313: V/DummyFragment(12783): onActivityCreated
01-05 23:54:22.313: V/DummyFragment(12783): onStart
01-05 23:54:22.323: V/MyFragmentActivity(12783): onResume
01-05 23:54:22.323: V/MyFragmentActivity(12783): onPostResume
01-05 23:54:22.323: V/MyFragmentActivity(12783): onResumeFragments
01-05 23:54:22.323: V/DummyFragment(12783): onResume
01-05 23:54:27.123: V/MyFragmentActivity(12783): onFriendAddedAsyncTask/onPostExecute
01-05 23:54:27.123: D/AndroidRuntime(12783): Shutting down VM
01-05 23:54:27.123: W/dalvikvm(12783): threadid=1: thread exiting with uncaught exception (group=0x4001d7d0)
01-05 23:54:27.138: E/AndroidRuntime(12783): FATAL EXCEPTION: main
01-05 23:54:27.138: E/AndroidRuntime(12783): Java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
01-05 23:54:27.138: E/AndroidRuntime(12783):    at Android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.Java:1314)
01-05 23:54:27.138: E/AndroidRuntime(12783):    at Android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.Java:1325)
01-05 23:54:27.138: E/AndroidRuntime(12783):    at Android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.Java:548)
01-05 23:54:27.138: E/AndroidRuntime(12783):    at Android.support.v4.app.BackStackRecord.commit(BackStackRecord.Java:532)
01-05 23:54:27.138: E/AndroidRuntime(12783):    at com.xyz.dummy.MyFragmentActivity$onFriendAddedAsyncTask.onPostExecute(MyFragmentActivity.Java:447)
01-05 23:54:27.138: E/AndroidRuntime(12783):    at com.xyz.dummy.MyFragmentActivity$onFriendAddedAsyncTask.onPostExecute(MyFragmentActivity.Java:1)
01-05 23:54:27.138: E/AndroidRuntime(12783):    at Android.os.AsyncTask.finish(AsyncTask.Java:417)
01-05 23:54:27.138: E/AndroidRuntime(12783):    at Android.os.AsyncTask.access$300(AsyncTask.Java:127)
01-05 23:54:27.138: E/AndroidRuntime(12783):    at Android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.Java:429)
01-05 23:54:27.138: E/AndroidRuntime(12783):    at Android.os.Handler.dispatchMessage(Handler.Java:99)
01-05 23:54:27.138: E/AndroidRuntime(12783):    at Android.os.Looper.loop(Looper.Java:123)
01-05 23:54:27.138: E/AndroidRuntime(12783):    at Android.app.ActivityThread.main(ActivityThread.Java:4627)
01-05 23:54:27.138: E/AndroidRuntime(12783):    at Java.lang.reflect.Method.invokeNative(Native Method)
01-05 23:54:27.138: E/AndroidRuntime(12783):    at Java.lang.reflect.Method.invoke(Method.Java:521)
01-05 23:54:27.138: E/AndroidRuntime(12783):    at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:858)
01-05 23:54:27.138: E/AndroidRuntime(12783):    at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:616)
01-05 23:54:27.138: E/AndroidRuntime(12783):    at dalvik.system.NativeStart.main(Native Method)

In anderen Threads zu ähnlichen Problemen scheint der Grund zu sein, dass die onPostExecute-Methode vor dem Aufruf der onResume () -Methode aufgerufen wird. Ich bekomme aber die Ausnahme, obwohl onResume () vorher aufgerufen wurde.

Weiß jemand was falsch ist?

Die Aktivität sieht so aus:

public class MyFragmentActivity extends FragmentActivity implements OnFriendSelectedListener, OnFriendAddedListener, OnFriendOptionSelectedListener, LoaderCallbacks<Cursor> {

@Override
public void onCreate(Bundle savedInstanceState) {
    Log.v("MyFragmentActivity", "onCreate");
    super.onCreate(savedInstanceState);
    setContentView(R.layout.fragment_activity_layout);
    FragmentManager fm = getSupportFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();
    FriendListFragment friendListFragment = (FriendListFragment)fm.findFragmentById(R.id.friend_list_fragment_layout);
    if (friendListFragment == null) {
        friendListFragment = new FriendListFragment(); 
        ft.add(R.id.friend_list_fragment_layout, friendListFragment);
        ft.commit();
        fm.executePendingTransactions();
        startService(new Intent(this, MyIntentService.class));
        getSupportLoaderManager().initLoader(CHECK_EMPTY_DATABASE, null, this);
    }
}

    @Override
public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);
    getMenuInflater().inflate(R.menu.fragment_activity_options_menu, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    super.onOptionsItemSelected(item);
    switch (item.getItemId()) {
    case R.id.add_friend_menu_item:
        AddFriendDialogFragment addFriendDialogFragment = AddFriendDialogFragment.newInstance();
        addFriendDialogFragment.show(getSupportFragmentManager(), "add_friend_dialog_fragment");
        return true;
    default:
        return false;
    }
}

@Override
public void onFriendAdded(String name) {
    name = name.trim();
    if (name.length() > 0) {
        new onFriendAddedAsyncTask().execute(name);
    }
}

Bei Verwendung von commitAllowingStateLoss () erhalte ich die folgende Ausnahme:

01-06 14:54:29.548: E/AndroidRuntime(18020): FATAL EXCEPTION: main
01-06 14:54:29.548: E/AndroidRuntime(18020): Java.lang.IllegalStateException: Activity has been destroyed
01-06 14:54:29.548: E/AndroidRuntime(18020):    at Android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.Java:1329)
01-06 14:54:29.548: E/AndroidRuntime(18020):    at Android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.Java:548)
01-06 14:54:29.548: E/AndroidRuntime(18020):    at Android.support.v4.app.BackStackRecord.commitAllowingStateLoss(BackStackRecord.Java:536)
01-06 14:54:29.548: E/AndroidRuntime(18020):    at com.xyz.dummy.FadiaFragmentActivity$onFriendAddedAsyncTask.onPostExecute(FadiaFragmentActivity.Java:461)
01-06 14:54:29.548: E/AndroidRuntime(18020):    at com.xyz.dummy.FadiaFragmentActivity$onFriendAddedAsyncTask.onPostExecute(FadiaFragmentActivity.Java:1)
01-06 14:54:29.548: E/AndroidRuntime(18020):    at Android.os.AsyncTask.finish(AsyncTask.Java:417)
01-06 14:54:29.548: E/AndroidRuntime(18020):    at Android.os.AsyncTask.access$300(AsyncTask.Java:127)
01-06 14:54:29.548: E/AndroidRuntime(18020):    at Android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.Java:429)
01-06 14:54:29.548: E/AndroidRuntime(18020):    at Android.os.Handler.dispatchMessage(Handler.Java:99)
01-06 14:54:29.548: E/AndroidRuntime(18020):    at Android.os.Looper.loop(Looper.Java:123)
01-06 14:54:29.548: E/AndroidRuntime(18020):    at Android.app.ActivityThread.main(ActivityThread.Java:4627)
01-06 14:54:29.548: E/AndroidRuntime(18020):    at Java.lang.reflect.Method.invokeNative(Native Method)
01-06 14:54:29.548: E/AndroidRuntime(18020):    at Java.lang.reflect.Method.invoke(Method.Java:521)
01-06 14:54:29.548: E/AndroidRuntime(18020):    at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:858)
01-06 14:54:29.548: E/AndroidRuntime(18020):    at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:616)
01-06 14:54:29.548: E/AndroidRuntime(18020):    at dalvik.system.NativeStart.main(Native Method)

Ich erhalte dieselbe IllegalStateExeption, wenn ich AsynTask wie folgt implementiere, da die findFragmentById () - Methode einen Nullzeiger zurückgibt.

private class onFriendAddedAsyncTask extends AsyncTask<String, Void, String> {

    protected void onPreExecute() {
        Log.v("MyFragmentActivity", "onFriendAddedAsyncTask/onPreExecute");
        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        DummyFragment dummyFragment = DummyFragment.newInstance();
        ft.add(R.id.dummy_fragment_layout, dummyFragment);
        ft.commit();
    }

    protected void onPostExecute(String result) {
        Log.v("MyFragmentActivity", "onFriendAddedAsyncTask/onPostExecute");
        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        DummyFragment dummyFragment = (DummyFragment) fm.findFragmentById(R.id.dummy_fragment_layout);
        ft.remove(dummyFragment);
        ft.commitAllowingStateLoss();
    }

Im nächsten Schritt verwende ich einen Handler, um das DummyFragment hinzuzufügen und zu entfernen. Zusätzlich habe ich noch einige Debug-Ausgaben hinzugefügt.

private class onFriendAddedAsyncTask extends AsyncTask<String, Void, String> {

    @Override
    protected void onPreExecute() {
        Log.v("MyFragmentActivity", "onFriendAddedAsyncTask/onPreExecute " + getSupportFragmentManager());
        Log.v("MyFragmentActivity", "onFriendAddedAsyncTask/onPreExecute " + getSupportFragmentManager().findFragmentById(R.id.dummy_fragment_layout));
        Log.v("MyFragmentActivity", "onFriendAddedAsyncTask/onPreExecute " + getSupportFragmentManager().findFragmentById(R.id.friend_list_fragment_layout));

        new Handler().post(new Runnable() {
            public void run() {
                Log.v("MyFragmentActivity", "onFriendAddedAsyncTask/onPreExecute " + getSupportFragmentManager());
                Log.v("MyFragmentActivity", "onFriendAddedAsyncTask/onPreExecute " + getSupportFragmentManager().findFragmentById(R.id.dummy_fragment_layout));
                Log.v("MyFragmentActivity", "onFriendAddedAsyncTask/onPreExecute " + getSupportFragmentManager().findFragmentById(R.id.friend_list_fragment_layout));
                FragmentManager fm = getSupportFragmentManager();
                FragmentTransaction ft = fm.beginTransaction();
                DummyFragment dummyFragment = DummyFragment.newInstance();
                ft.add(R.id.dummy_fragment_layout, dummyFragment);
                ft.commit();
            }
        });

    @Override
    protected void onPostExecute(String result) {
        Log.v("MyFragmentActivity", "onFriendAddedAsyncTask/onPostExecute " + getSupportFragmentManager());
        Log.v("MyFragmentActivity", "onFriendAddedAsyncTask/onPostExecute " + getSupportFragmentManager().findFragmentById(R.id.dummy_fragment_layout));
        Log.v("MyFragmentActivity", "onFriendAddedAsyncTask/onPostExecute " + getSupportFragmentManager().findFragmentById(R.id.friend_list_fragment_layout));

        new Handler().post(new Runnable() {
            public void run() {
                Log.v("MyFragmentActivity", "onFriendAddedAsyncTask/onPostExecute " + getSupportFragmentManager());
                Log.v("MyFragmentActivity", "onFriendAddedAsyncTask/onPostExecute " + getSupportFragmentManager().findFragmentById(R.id.dummy_fragment_layout));
                Log.v("MyFragmentActivity", "onFriendAddedAsyncTask/onPostExecute " + getSupportFragmentManager().findFragmentById(R.id.friend_list_fragment_layout));
                FragmentManager fm = getSupportFragmentManager();
                FragmentTransaction ft = fm.beginTransaction();
                DummyFragment dummyFragment = (DummyFragment) fm.findFragmentById(R.id.dummy_fragment_layout);
                ft.remove(dummyFragment);
                ft.commitAllowingStateLoss();
            }
        });

Ich bekomme folgendes LogCut:

01-07 19:00:17.273: V/MyFragmentActivity(4124): onFriendAddedAsyncTask/onPreExecute FragmentManager{45e384a8 in MyFragmentActivity{45e38358}}
01-07 19:00:17.273: V/MyFragmentActivity(4124): onFriendAddedAsyncTask/onPreExecute null
01-07 19:00:17.273: V/MyFragmentActivity(4124): onFriendAddedAsyncTask/onPreExecute FriendListFragment{45e38ab0 #0 id=0x7f0a0002}
01-07 19:00:17.283: V/MyFragmentActivity(4124): onFriendAddedAsyncTask/onPreExecute FragmentManager{45e384a8 in MyFragmentActivity{45e38358}}
01-07 19:00:17.288: V/MyFragmentActivity(4124): onFriendAddedAsyncTask/doInBackground
01-07 19:00:17.288: V/MyFragmentActivity(4124): onFriendAddedAsyncTask/onPreExecute null
01-07 19:00:17.288: V/MyFragmentActivity(4124): onFriendAddedAsyncTask/onPreExecute FriendListFragment{45e38ab0 #0 id=0x7f0a0002}
01-07 19:00:17.308: V/DummyFragment(4124): onAttach DummyFragment{45dd7498 #2 id=0x7f0a0004}
01-07 19:00:17.308: V/DummyFragment(4124): onCreate DummyFragment{45dd7498 #2 id=0x7f0a0004}
01-07 19:00:17.308: V/DummyFragment(4124): onCreateView DummyFragment{45dd7498 #2 id=0x7f0a0004}
01-07 19:00:17.308: V/DummyFragment(4124): onActivityCreated DummyFragment{45dd7498 #2 id=0x7f0a0004}
01-07 19:00:17.308: V/DummyFragment(4124): onStart DummyFragment{45dd7498 #2 id=0x7f0a0004}
01-07 19:00:17.313: V/DummyFragment(4124): onResume DummyFragment{45dd7498 #2 id=0x7f0a0004}
01-07 19:00:18.098: V/MyFragmentActivity(4124): onSaveInstanceState DummyFragment{45dd7498 #2 id=0x7f0a0004}
01-07 19:00:18.098: V/DummyFragment(4124): onSaveInstanceState DummyFragment{45dd7498 #2 id=0x7f0a0004}
01-07 19:00:18.098: V/MyFragmentActivity(4124): onPause DummyFragment{45dd7498 #2 id=0x7f0a0004}
01-07 19:00:18.098: V/DummyFragment(4124): onPause DummyFragment{45dd7498 #2 id=0x7f0a0004}
01-07 19:00:18.103: V/MyFragmentActivity(4124): onStop DummyFragment{45dd7498 #2 id=0x7f0a0004}
01-07 19:00:18.103: V/DummyFragment(4124): onStop DummyFragment{45dd7498 #2 id=0x7f0a0004}
01-07 19:00:18.103: V/MyFragmentActivity(4124): onDestroy DummyFragment{45dd7498 #2 id=0x7f0a0004}
01-07 19:00:18.103: V/DummyFragment(4124): onDestroyView DummyFragment{45dd7498 #2 id=0x7f0a0004}
01-07 19:00:18.108: V/DummyFragment(4124): onDestroy DummyFragment{45dd7498 #2 id=0x7f0a0004}
01-07 19:00:18.113: V/DummyFragment(4124): onDetach DummyFragment{45dd7498 #2 id=0x7f0a0004}
01-07 19:00:18.138: V/MyFragmentActivity(4124): onCreate
01-07 19:00:18.138: V/FriendListFragment(4124): FriendListFragment
01-07 19:00:18.138: V/FriendListFragment(4124): onAttach FriendListFragment{45e4a7f8 #0 id=0x7f0a0002}
01-07 19:00:18.138: V/FriendListFragment(4124): onCreate FriendListFragment{45e4a7f8 #0 id=0x7f0a0002}
01-07 19:00:18.148: V/DummyFragment(4124): onAttach DummyFragment{45d7d1a0 #2 id=0x7f0a0004}
01-07 19:00:18.153: V/DummyFragment(4124): onCreate DummyFragment{45d7d1a0 #2 id=0x7f0a0004}
01-07 19:00:18.523: V/MyFragmentActivity(4124): onStart DummyFragment{45d7d1a0 #2 id=0x7f0a0004}
01-07 19:00:18.543: V/FriendListFragment(4124): onActivityCreated FriendListFragment{45e4a7f8 #0 id=0x7f0a0002}
01-07 19:00:18.548: V/DummyFragment(4124): onCreateView DummyFragment{45d7d1a0 #2 id=0x7f0a0004}
01-07 19:00:18.548: V/DummyFragment(4124): onActivityCreated DummyFragment{45d7d1a0 #2 id=0x7f0a0004}
01-07 19:00:18.548: V/FriendListFragment(4124): onLoadFinished FragmentManager{45d8e478 in MyFragmentActivity{45e4a6d8}}
01-07 19:00:18.548: V/FriendListFragment(4124): onLoadFinished FriendListFragment{45e4a7f8 #0 id=0x7f0a0002}
01-07 19:00:18.553: V/DummyFragment(4124): onStart DummyFragment{45d7d1a0 #2 id=0x7f0a0004}
01-07 19:00:18.553: V/FriendListFragment(4124): onLoadFinished FragmentManager{45d8e478 in MyFragmentActivity{45e4a6d8}}
01-07 19:00:18.553: V/FriendListFragment(4124): onLoadFinished FriendListFragment{45e4a7f8 #0 id=0x7f0a0002}
01-07 19:00:18.558: V/MyFragmentActivity(4124): onResume DummyFragment{45d7d1a0 #2 id=0x7f0a0004}
01-07 19:00:18.558: V/MyFragmentActivity(4124): onPostResume DummyFragment{45d7d1a0 #2 id=0x7f0a0004}
01-07 19:00:18.558: V/MyFragmentActivity(4124): onResumeFragments DummyFragment{45d7d1a0 #2 id=0x7f0a0004}
01-07 19:00:18.558: V/FriendListFragment(4124): onResume FriendListFragment{45e4a7f8 #0 id=0x7f0a0002}
01-07 19:00:18.563: V/FriendListFragment(4124): onCreateLoader FriendListFragment{45e4a7f8 #0 id=0x7f0a0002}
01-07 19:00:18.563: V/DummyFragment(4124): onResume DummyFragment{45d7d1a0 #2 id=0x7f0a0004}
01-07 19:00:18.723: V/FriendListFragment(4124): onLoadFinished FragmentManager{45d8e478 in MyFragmentActivity{45e4a6d8}}
01-07 19:00:18.723: V/FriendListFragment(4124): onLoadFinished FriendListFragment{45e4a7f8 #0 id=0x7f0a0002}
01-07 19:00:18.893: V/MyFragmentActivity(4124): onFriendAddedAsyncTask/onPostExecute FragmentManager{45e384a8 in null}}
01-07 19:00:18.893: V/MyFragmentActivity(4124): onFriendAddedAsyncTask/onPostExecute null
01-07 19:00:18.893: V/MyFragmentActivity(4124): onFriendAddedAsyncTask/onPostExecute null
01-07 19:00:18.923: V/MyFragmentActivity(4124): onFriendAddedAsyncTask/onPostExecute FragmentManager{45e384a8 in null}}
01-07 19:00:18.923: V/MyFragmentActivity(4124): onFriendAddedAsyncTask/onPostExecute null
01-07 19:00:18.923: V/MyFragmentActivity(4124): onFriendAddedAsyncTask/onPostExecute null
01-07 19:00:18.928: D/AndroidRuntime(4124): Shutting down VM
01-07 19:00:18.928: W/dalvikvm(4124): threadid=1: thread exiting with uncaught exception (group=0x4001d7d0)
01-07 19:00:18.938: E/AndroidRuntime(4124): FATAL EXCEPTION: main
01-07 19:00:18.938: E/AndroidRuntime(4124): Java.lang.IllegalStateException: Activity has been destroyed
01-07 19:00:18.938: E/AndroidRuntime(4124):     at Android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.Java:1329)
01-07 19:00:18.938: E/AndroidRuntime(4124):     at Android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.Java:548)
01-07 19:00:18.938: E/AndroidRuntime(4124):     at Android.support.v4.app.BackStackRecord.commitAllowingStateLoss(BackStackRecord.Java:536)
01-07 19:00:18.938: E/AndroidRuntime(4124):     at com.xyz.dummy.MyFragmentActivity$onFriendAddedAsyncTask$2.run(MyFragmentActivity.Java:476)
01-07 19:00:18.938: E/AndroidRuntime(4124):     at Android.os.Handler.handleCallback(Handler.Java:587)
01-07 19:00:18.938: E/AndroidRuntime(4124):     at Android.os.Handler.dispatchMessage(Handler.Java:92)
01-07 19:00:18.938: E/AndroidRuntime(4124):     at Android.os.Looper.loop(Looper.Java:123)
01-07 19:00:18.938: E/AndroidRuntime(4124):     at Android.app.ActivityThread.main(ActivityThread.Java:4627)
01-07 19:00:18.938: E/AndroidRuntime(4124):     at Java.lang.reflect.Method.invokeNative(Native Method)
01-07 19:00:18.938: E/AndroidRuntime(4124):     at Java.lang.reflect.Method.invoke(Method.Java:521)
01-07 19:00:18.938: E/AndroidRuntime(4124):     at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:858)
01-07 19:00:18.938: E/AndroidRuntime(4124):     at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:616)
01-07 19:00:18.938: E/AndroidRuntime(4124):     at dalvik.system.NativeStart.main(Native Method)

In onPreExecute () hat FriendListFragment die ID = 0x7f0a0002. Im Handler wird das DummyFragment mit der ID = 0x7f0a0004 erstellt. In onPostExecute () sind beide IDs null ..__ In OnPreExecute () ist die Adresse von MyFragmentActivity 45e38358. aber in onPostExecute () ist es null. In beiden Methoden lautet die FragmentManager-Adresse jedoch 45e384a8 . Ich denke, onPostExecute verwendet einen ungültigen FragmentManager. Aber warum?

130
samo

Sie sollten die Transaktion in einer Handler wie folgt durchführen:

@Override
protected void onPostExecute(String result) {
    Log.v("MyFragmentActivity", "onFriendAddedAsyncTask/onPostExecute");
    new Handler().post(new Runnable() {
            public void run() {
                fm = getSupportFragmentManager();
                ft = fm.beginTransaction();
                ft.remove(dummyFragment);
                ft.commit();
            }
        });
}
95
Oleg Vaskevich

Danke Oleg Vaskevich. Die Verwendung eines WeakReference des FragmentActivity löste das Problem. Mein Code sieht jetzt folgendermaßen aus:

public class MyFragmentActivity extends FragmentActivity implements OnFriendAddedListener {

    private static WeakReference<MyFragmentActivity> wrActivity = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        wrActivity = new WeakReference<MyFragmentActivity>(this);
        ...

    private class onFriendAddedAsyncTask extends AsyncTask<String, Void, String> {

        @Override
        protected void onPreExecute() {
            FragmentManager fm = getSupportFragmentManager();
            FragmentTransaction ft = fm.beginTransaction();
            DummyFragment dummyFragment = DummyFragment.newInstance();
            ft.add(R.id.dummy_fragment_layout, dummyFragment);
            ft.commit();
        }

        @Override
        protected void onPostExecute(String result) {
            final Activity activity = wrActivity.get();
            if (activity != null && !activity.isFinishing()) {
                FragmentManager fm = activity.getSupportFragmentManager();
                FragmentTransaction ft = fm.beginTransaction();
                DummyFragment dummyFragment = (DummyFragment) fm.findFragmentById(R.id.dummy_fragment_layout);
                ft.remove(dummyFragment);
                ft.commitAllowingStateLoss();
            }
        }
53
samo

Ich glaube, die richtige Antwort auf diese Frage ist die folgende Methode.

public abstract int commitAllowingStateLoss ()

Wie commit (), ermöglicht jedoch die Ausführung des Commits nach einer Zustand wird gespeichert. Dies ist gefährlich, da das Festschreiben verloren gehen kann, wenn Die Aktivität muss später aus ihrem Zustand wiederhergestellt werden. Dies sollte nur für Fälle verwendet werden, in denen der UI-Status in Ordnung ist unerwartet für den Benutzer.

Die vorstehende Beschreibung bezieht sich auf dieses Verfahren.

protected void onSaveInstanceState(Android.os.Bundle outState)

Dieses Problem tritt genau dann auf, wenn das Gerät in den Ruhezustand wechselt.

http://developer.Android.com/reference/Android/app/FragmentTransaction.html

35
alex

Kurze und funktionierende Lösung:

Folgen Sie einfachen Schritten:

Schritt 1 : Überschreibt den onSaveInstanceState-Status im jeweiligen Fragment. Und super Methode daraus entfernen.

@Override
public void onSaveInstanceState(Bundle outState) {
}

Schritt 2 : Verwenden Sie beim Fragmentieren von Operationen CommitAllowingStateLoss(); anstelle von commit();.

fragmentTransaction.commitAllowingStateLoss();
24
Basbous

Prüfen Sie, ob die Aktivität isFinishing() angezeigt wird, bevor Sie das Fragment anzeigen.

Beispiel:

if(!isFinishing()) {
FragmentManager fm = getSupportFragmentManager();
            FragmentTransaction ft = fm.beginTransaction();
            DummyFragment dummyFragment = DummyFragment.newInstance();
            ft.add(R.id.dummy_fragment_layout, dummyFragment);
            ft.commitAllowingStateLoss();
}
10
Naskov

Ich hatte ein ähnliches Problem, das ich durch Verschieben eines Fragmenttransaktionscodes von onResume() in onStart() behoben habe.

Genauer gesagt: Meine App ist ein Startprogramm. Nach dem Drücken der Android-Home-Taste kann der Benutzer ein Startprogramm auswählen, bis seine Entscheidung gespeichert wird. Beim Zurückgehen an dieser Stelle (z. B. durch Tippen auf den grauen Bereich) stürzte die App ab.

Vielleicht hilft das jemandem.

5
Alex

Es gibt eine alternative Lösung (NICHT die beste Lösung) für dieses Problem, funktioniert jedoch. Mit flag kannst du damit umgehen, wie unten

/**
 * Flag to avoid "Java.lang.IllegalStateException: Can not perform this action after
 * onSaveInstanceState". Avoid Fragment transaction until onRestoreInstanceState or onResume
 * gets called.
 */
private boolean isOnSaveInstanceStateCalled = false;


@Override
public void onRestoreInstanceState(final Bundle bundle) {
    .....
    isOnSaveInstanceStateCalled = false;
    .....
}

@Override
public void onSaveInstanceState(final Bundle outState) {
    .....
    isOnSaveInstanceStateCalled = true;
    .....
}

@Override
public void onResume() {
    super.onResume();
    isOnSaveInstanceStateCalled = false;
    .....
}

Sie können diesen boolean-Wert während der Fragmenttransaktion überprüfen.

private void fragmentReplace(Fragment fragment, String fragmentTag){
    if (!isOnSaveInstanceStateCalled) {
        getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.layout_container, fragment, fragmentTag)
                .commit();
    }
}
2
Pankaj Kumar

Das passierte für mich, weil ich commit() aus einem Subfragment anrief, das Aktivität ausläuft. Es behielt die Aktivität als Eigenschaft bei, und eine Rotationsaktivitätsvariable wurde nicht von onAttach(); aktualisiert. Daher versuchte ich, eine Transaktion für Zombie-Aktivität durch ein beibehaltenes (setRetainInstance(true);)-Fragment festzuschreiben.

2
Malachiasz

Verwenden Sie commitAllowingStateLoss() anstelle von commit().

wenn Sie commit() verwenden, kann eine Ausnahme ausgelöst werden, wenn ein Statusverlust auftritt. commitAllowingStateLoss() speichert jedoch die Transaktion ohne Statusverlust, so dass bei einem Statusverlust keine Ausnahme ausgelöst wird.

2
felhi

Der Grund für die Ausnahme ist die erneute Erstellung der FragmentActivity während der Laufzeit der AsyncTask und der anschließende Zugriff auf die vorher zerstörte FragmentActivity in onPostExecute().

Das Problem besteht darin, einen gültigen Verweis auf die neue FragmentActivity zu erhalten. Es gibt keine Methode dafür, weder getActivity() noch findById() oder ähnliches. Dieses Forum enthält eine Fülle von Threads zu diesem Problem (z. B. Suche nach "Activity context in onPostExecute"). Einige von ihnen beschreiben Workarounds (bis jetzt habe ich keine gute gefunden).

Vielleicht wäre es eine bessere Lösung, einen Dienst für meine Zwecke zu nutzen.

2
samo

Lösung 1: Überschreiben Sie onSaveInstanceState() und entfernen Sie den Superaufruf darin.

@Override
public void onSaveInstanceState(Bundle outState) {
}

Lösung 2: Überschreiben Sie onSaveInstanceState() und entfernen Sie Ihr Fragment vor dem Superaufruf

@Override
public void onSaveInstanceState(Bundle outState) {
     // TODO: Add code to remove fragment here
     super.onSaveInstanceState(outState);
}
1
Lingkun Kong

Für was es wert ist; Ich hatte diesen Fehler bei einer App, bei der im Hintergrund Dienste ausgeführt wurden. Bei einem davon musste dem Benutzer ein Timeout-Dialog angezeigt werden. Dieses Dialogfeld war das Problem, das zu diesem Fehler führte, wenn die App nicht mehr im Vordergrund ausgeführt wurde.

In unserem Fall war die Anzeige des Dialogs nicht hilfreich, wenn sich die App im Hintergrund befand. Deshalb haben wir dies einfach nachverfolgt (boolesches Flag onPause en onResume) und das Dialogfeld nur dann anzeigen, wenn die App für den Benutzer tatsächlich sichtbar ist.

1
hcpl

Dieses Problem tritt auf, wenn ein Prozess versucht, eine Aktivität zu bearbeiten, deren onStop() aufgerufen wurde. Es ist nicht unbedingt an das Fragmentieren von Transaktionen gebunden, sondern auch an andere Methoden wie onBackPressed ().

Neben AsyncTask besteht eine weitere Ursache für dieses Problem darin, dass das Abonnement des Busmusters falsch platziert wird. Normalerweise wird das Event Bus- oder RxBus-Abonnement während von onCreate registriert und in onDestroy abgemeldet. Wenn eine neue Aktivität gestartet wird und ein Ereignis veröffentlicht wird, das von Abonnenten der vorherigen Aktivität abgefangen wird, kann dieser Fehler ausgegeben werden. In diesem Fall können Sie die Registrierung und Abmeldung des Abonnements nach onStart() und onStop() verschieben. 

1
inmyth

Ab der Support Library Version 24.0.0 können Sie die FragmentTransaction.commitNow()-Methode aufrufen, die diese Transaktion synchron festschreibt, anstatt commit() aufzurufen, gefolgt von executePendingTransactions().

IllegalStateException tritt auf, wenn Sie eine Fragmenttransaktion festschreiben, nachdem die Aktivität ihren Status verloren hat. Die Aktivität steht nicht im Vordergrund. Dies tritt häufig auf, wenn Sie versuchen, ein Fragment in AsyncTask oder nach einer Netzwerkanforderung zu übergeben. 

Um diesen Absturz zu vermeiden, müssen Sie lediglich eine Fragmenttransaktion verzögern, bis der Aktivitätsstatus wiederhergestellt ist. Im Folgenden wird beschrieben, wie es gemacht wird

Deklarieren Sie zwei private boolesche Variablen

public class MainActivity extends AppCompatActivity {

    //Boolean variable to mark if the transaction is safe
    private boolean isTransactionSafe;

    //Boolean variable to mark if there is any transaction pending
    private boolean isTransactionPending;

Jetzt in onPostResume () und onPause setzen wir unsere boolesche Variable isTransactionSafe. Die Idee ist, trasnsaction nur dann als sicher zu kennzeichnen, wenn die Aktivität im Vordergrund steht, so dass keine Gefahr von Statusverlust besteht.

/*
onPostResume is called only when the activity's state is completely restored. In this we will
set our boolean variable to true. Indicating that transaction is safe now
 */
public void onPostResume(){
    super.onPostResume();
    isTransactionSafe=true;
}
/*
onPause is called just before the activity moves to background and also before onSaveInstanceState. In this
we will mark the transaction as unsafe
 */

public void onPause(){
    super.onPause();
    isTransactionSafe=false;

}

private void commitFragment(){
    if(isTransactionSafe) {
        MyFragment myFragment = new MyFragment();
        FragmentManager fragmentManager = getFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.add(R.id.frame, myFragment);
        fragmentTransaction.commit();
    }
}

Was wir bisher getan haben, wird aus IllegalStateException retten, aber unsere Transaktionen gehen verloren, wenn sie ausgeführt werden, nachdem die Aktivität in den Hintergrund verschoben wurde, ähnlich wie commitAllowStateloss (). Um dies zu unterstützen, haben wir die boolesche Variable isTransactionPending

public void onPostResume(){
   super.onPostResume();
   isTransactionSafe=true;
/* Here after the activity is restored we check if there is any transaction pending from
the last restoration
*/
   if (isTransactionPending) {
      commitFragment();
   }
}


private void commitFragment(){

 if(isTransactionSafe) {
     MyFragment myFragment = new MyFragment();
     FragmentManager fragmentManager = getFragmentManager();
     FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
     fragmentTransaction.add(R.id.frame, myFragment);
     fragmentTransaction.commit();
     isTransactionPending=false;
 }else {
     /*
     If any transaction is not done because the activity is in background. We set the
     isTransactionPending variable to true so that we can pick this up when we come back to
foreground
     */
     isTransactionPending=true;
 }
}

Dieser Artikel erklärt ganz genau, warum diese Ausnahme auftritt, und vergleicht verschiedene Methoden, um sie zu beheben. Sehr empfehlenswert

0
IrshadKumail

Meine App hat ein Fragment zum Laden in 3 Sekunden, aber wenn der erste Bildschirm sich für die Anzeige vorbereitet, drücke ich die Start-Taste und führe die Ausführung erneut aus. Es wird derselbe Fehler angezeigt. Es bearbeitet also meinen Code und es lief sehr glatt:

new Handler().post(new Runnable() {
        public void run() {
            if (saveIns == null) {
                mFragment = new Fragment_S1_loading();
                getFragmentManager().beginTransaction()
                        .replace(R.id.container, mFragment).commit();
            }
            getActionBar().hide();
            // Loading screen in 3 secs:
            mCountDownTimerLoading = new CountDownTimer(3000, 1000) {

                @Override
                public void onTick(long millisUntilFinished) {

                }

                @Override
                public void onFinish() {
                    if (saveIns == null) {// TODO bug when start app and press home
                                            // button
                        getFragmentManager()
                                .beginTransaction()
                                .replace(R.id.container,
                                        new Fragment_S2_sesstion1()).commitAllowingStateLoss();
                    }
                    getActionBar().show();
                }
            }.start();
        }
    });

HINWEIS: füge commitAllowingStateLoss () anstelle von commit () hinzu

0
nobjta_9x_tq

Ich hatte die gleiche Ausnahme und habe viele Snippets ausprobiert, die ich hier in dieser Stackoverflow-Diskussion gefunden habe, aber für mich funktionierten keine Snippets. 

Aber ich konnte alle Probleme lösen, ich werde die Lösungen mit Ihnen teilen:

  • In einem ersten Teil: Ich habe versucht, ein DialogFragment in einer Activity anzuzeigen, aber von einer anderen Java-Klasse. Als ich dann das Attribut dieser Instanz überprüfte, stellte ich fest, dass es sich um eine alte Instanz der Aktivität und nicht um die aktuell ausgeführte Aktivität handelte. [Genauer gesagt, ich habe socket.io verwendet und ich habe vergessen, eine socket.off ("example", Beispiel) zu machen ... also an eine alte Instanz der Aktivität angehängt. ]

  • Zweiter Teil: Ich habe versucht, ein DialogFragment in einer Activity anzuzeigen, wenn ich mit einer Absicht zurückkomme, aber als ich meine Protokolle überprüfte, stellte ich fest, dass die Aktivität immer noch nicht in der onStart-Methode war Also stürzte die App ab, weil sie die Activity-Klasse nicht fand, um das Fragment darauf zu zeigen. 

Einige Tipps: Überprüfen Sie mit einigen Attributen, ob Sie keine alte Instanz Ihrer Aktivität verwenden, mit der Sie Ihr Fragment anzeigen möchten, oder überprüfen Sie den Aktivitätslebenszyklus, bevor Sie Ihr Fragment anzeigen, und stellen Sie sicher, dass Sie sich in onStart oder onResume befinden, bevor Sie es anzeigen . 

Ich hoffe, diese Erklärungen werden Ihnen helfen. 

0
Raj