java.lang.IllegalStateException:onSaveInstanceState 后无法执行此操作

Posted

技术标签:

【中文标题】java.lang.IllegalStateException:onSaveInstanceState 后无法执行此操作【英文标题】:java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState 【发布时间】:2012-12-20 02:38:11 【问题描述】:

我正在为我的应用程序使用支持库。在我的 FragmentActivity 中,我使用 AsyncTask 从互联网下载数据。在 onPreExecute() 方法中,我添加了一个 Fragment,在 onPostExecute() 方法中,我再次将其删除。当两者之间的方向发生变化时,我得到了上述异常。请看详情:

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

我得到以下 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)

在其他关于类似问题的线程中,原因似乎是在调用 onResume() 方法之前调用了 onPostExecute 方法。但即使之前调用了 onResume(),我也会遇到异常。

有人知道出了什么问题吗?

Activity 看起来像这样:

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

使用 commitAllowingStateLoss() 时出现以下异常:

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)

当我如下实现 AsynTask 时,我得到了相同的 IllegalStateExeption,因为 findFragmentById() 方法返回一个空指针。

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

在下一步中,我使用一个处理程序来添加和删除 DummyFragment。此外,我还添加了一些调试输出。

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

我得到以下 LogCut:

01-07 19:00:17.273: V/MyFragmentActivity(4124): onFriendAddedAsyncTask/onPreExecute FragmentManager45e384a8 in MyFragmentActivity45e38358
01-07 19:00:17.273: V/MyFragmentActivity(4124): onFriendAddedAsyncTask/onPreExecute null
01-07 19:00:17.273: V/MyFragmentActivity(4124): onFriendAddedAsyncTask/onPreExecute FriendListFragment45e38ab0 #0 id=0x7f0a0002
01-07 19:00:17.283: V/MyFragmentActivity(4124): onFriendAddedAsyncTask/onPreExecute FragmentManager45e384a8 in MyFragmentActivity45e38358
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 FriendListFragment45e38ab0 #0 id=0x7f0a0002
01-07 19:00:17.308: V/DummyFragment(4124): onAttach DummyFragment45dd7498 #2 id=0x7f0a0004
01-07 19:00:17.308: V/DummyFragment(4124): onCreate DummyFragment45dd7498 #2 id=0x7f0a0004
01-07 19:00:17.308: V/DummyFragment(4124): onCreateView DummyFragment45dd7498 #2 id=0x7f0a0004
01-07 19:00:17.308: V/DummyFragment(4124): onActivityCreated DummyFragment45dd7498 #2 id=0x7f0a0004
01-07 19:00:17.308: V/DummyFragment(4124): onStart DummyFragment45dd7498 #2 id=0x7f0a0004
01-07 19:00:17.313: V/DummyFragment(4124): onResume DummyFragment45dd7498 #2 id=0x7f0a0004
01-07 19:00:18.098: V/MyFragmentActivity(4124): onSaveInstanceState DummyFragment45dd7498 #2 id=0x7f0a0004
01-07 19:00:18.098: V/DummyFragment(4124): onSaveInstanceState DummyFragment45dd7498 #2 id=0x7f0a0004
01-07 19:00:18.098: V/MyFragmentActivity(4124): onPause DummyFragment45dd7498 #2 id=0x7f0a0004
01-07 19:00:18.098: V/DummyFragment(4124): onPause DummyFragment45dd7498 #2 id=0x7f0a0004
01-07 19:00:18.103: V/MyFragmentActivity(4124): onStop DummyFragment45dd7498 #2 id=0x7f0a0004
01-07 19:00:18.103: V/DummyFragment(4124): onStop DummyFragment45dd7498 #2 id=0x7f0a0004
01-07 19:00:18.103: V/MyFragmentActivity(4124): onDestroy DummyFragment45dd7498 #2 id=0x7f0a0004
01-07 19:00:18.103: V/DummyFragment(4124): onDestroyView DummyFragment45dd7498 #2 id=0x7f0a0004
01-07 19:00:18.108: V/DummyFragment(4124): onDestroy DummyFragment45dd7498 #2 id=0x7f0a0004
01-07 19:00:18.113: V/DummyFragment(4124): onDetach DummyFragment45dd7498 #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 FriendListFragment45e4a7f8 #0 id=0x7f0a0002
01-07 19:00:18.138: V/FriendListFragment(4124): onCreate FriendListFragment45e4a7f8 #0 id=0x7f0a0002
01-07 19:00:18.148: V/DummyFragment(4124): onAttach DummyFragment45d7d1a0 #2 id=0x7f0a0004
01-07 19:00:18.153: V/DummyFragment(4124): onCreate DummyFragment45d7d1a0 #2 id=0x7f0a0004
01-07 19:00:18.523: V/MyFragmentActivity(4124): onStart DummyFragment45d7d1a0 #2 id=0x7f0a0004
01-07 19:00:18.543: V/FriendListFragment(4124): onActivityCreated FriendListFragment45e4a7f8 #0 id=0x7f0a0002
01-07 19:00:18.548: V/DummyFragment(4124): onCreateView DummyFragment45d7d1a0 #2 id=0x7f0a0004
01-07 19:00:18.548: V/DummyFragment(4124): onActivityCreated DummyFragment45d7d1a0 #2 id=0x7f0a0004
01-07 19:00:18.548: V/FriendListFragment(4124): onLoadFinished FragmentManager45d8e478 in MyFragmentActivity45e4a6d8
01-07 19:00:18.548: V/FriendListFragment(4124): onLoadFinished FriendListFragment45e4a7f8 #0 id=0x7f0a0002
01-07 19:00:18.553: V/DummyFragment(4124): onStart DummyFragment45d7d1a0 #2 id=0x7f0a0004
01-07 19:00:18.553: V/FriendListFragment(4124): onLoadFinished FragmentManager45d8e478 in MyFragmentActivity45e4a6d8
01-07 19:00:18.553: V/FriendListFragment(4124): onLoadFinished FriendListFragment45e4a7f8 #0 id=0x7f0a0002
01-07 19:00:18.558: V/MyFragmentActivity(4124): onResume DummyFragment45d7d1a0 #2 id=0x7f0a0004
01-07 19:00:18.558: V/MyFragmentActivity(4124): onPostResume DummyFragment45d7d1a0 #2 id=0x7f0a0004
01-07 19:00:18.558: V/MyFragmentActivity(4124): onResumeFragments DummyFragment45d7d1a0 #2 id=0x7f0a0004
01-07 19:00:18.558: V/FriendListFragment(4124): onResume FriendListFragment45e4a7f8 #0 id=0x7f0a0002
01-07 19:00:18.563: V/FriendListFragment(4124): onCreateLoader FriendListFragment45e4a7f8 #0 id=0x7f0a0002
01-07 19:00:18.563: V/DummyFragment(4124): onResume DummyFragment45d7d1a0 #2 id=0x7f0a0004
01-07 19:00:18.723: V/FriendListFragment(4124): onLoadFinished FragmentManager45d8e478 in MyFragmentActivity45e4a6d8
01-07 19:00:18.723: V/FriendListFragment(4124): onLoadFinished FriendListFragment45e4a7f8 #0 id=0x7f0a0002
01-07 19:00:18.893: V/MyFragmentActivity(4124): onFriendAddedAsyncTask/onPostExecute FragmentManager45e384a8 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 FragmentManager45e384a8 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)

在 onPreExecute() 中,FriendListFragment 的 id=0x7f0a0002。在处理程序内部,DummyFragment 使用 id=0x7f0a0004 创建。在 onPostExecute() 中,两个 ID 都为空。 在 onPreExecute() 中,MyFragmentActivity 的地址是 45e38358。但在 onPostExecute() 它是空的。但在这两种方法中,FragmentManager 地址都是 45e384a8。 我猜 onPostExecute 使用了无效的 FragmentManager。但为什么呢?

【问题讨论】:

我曾经遇到过这个问题,并通过将提交替换为:commitAllowingStateLoss(),你可以试试这个吗? 我已经尝试过了,但没有成功。根据 LogCat,Fragment 应该处于正确的状态。 您能发布您的活动代码吗? 当我使用 commitAllowingStateLoss() 我得到一个不同的异常(见上文)。 对于那些仍在寻找解决方案的人...有关此主题的更多信息,请参阅blog post 【参考方案1】:

您应该在Handler 中进行如下交易:

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

【讨论】:

没用。行为和以前一样。 @samo 请问您解决了这个问题吗?我有一个非常相似的情况link 考虑这个代码:private static WeakReference&lt;FragmentActivity&gt; mActivity = null; 简而言之,WeakReference 可以防止您泄漏活动...您需要调用mActivity.get() 才能真正获取实例,如果活动被破坏,它将为空。要更新它,您需要写mActivity = new WeakReference&lt;FragmentActivity&gt;(this); - 一个好地方是onCreate() - 这将更新参考。 对于那些仍在寻找解决方案的人...有关此主题的更多信息,请参阅blog post【参考方案2】:

感谢奥列格·瓦斯克维奇。使用FragmentActivityWeakReference 解决了这个问题。我的代码现在如下所示:

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

【讨论】:

弱引用的想法确实是一个非常聪明的想法,这样可以在必要时轻松地对对象进行垃圾回收。竖起大拇指萨摩! 这里为什么使用静态?如果我使用 MyFragmentActivity mActivity = this ? 没有静态和弱引用会怎样 静态引用是非常糟糕的工程,你应该将你的 asynchtask 绑定到生命周期并在必要时取消 弱引用仍然是一个愚蠢的想法。弱引用命名误导了很多人。只是要清楚;如果有对弱引用对象的引用,即使视图被销毁,您的视图仍然会泄漏【参考方案3】:

我相信这个问题的正确答案是下面的方法。

public abstract int commitAllowingStateLoss ()

与 commit() 类似,但允许在活动结束后执行提交 状态被保存。这是危险的,因为如果提交可能会丢失 活动需要稍后从其状态恢复,所以这应该 仅用于 UI 状态可以更改的情况 意外地在用户身上。

以上描述与此方法有关。

protected void onSaveInstanceState(android.os.Bundle outState)

此问题恰好在设备进入睡眠状态时发生。

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

【讨论】:

【参考方案4】:

短而有效的解决方案:

遵循简单的步骤:

第 1 步:覆盖各个片段中的 onSaveInstanceState 状态。并从中删除超级方法。

@Override
public void onSaveInstanceState(Bundle outState) 

第 2 步:在片段操作时使用CommitAllowingStateLoss(); 而不是commit();

fragmentTransaction.commitAllowingStateLoss();

【讨论】:

谢谢。这对我有用,但我知道这不是最好的解决方案。 移除超级方法,也会禁用保存片段状态。 非常感谢。它正在生成异常,此解决方案运行良好.. 我找不到onSaveInstanceState 方法。这是哪里?在我的片段中?它的超类是什么。【参考方案5】:

在显示片段之前检查活动isFinishing()

示例:

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

【讨论】:

【参考方案6】:

使用commitAllowingStateLoss() 代替commit()

当您使用commit() 时,如果发生状态丢失,它会抛出异常,但commitAllowingStateLoss() 保存事务而不丢失状态,因此如果发生状态丢失不会抛出异常。

【讨论】:

【参考方案7】:

我有一个类似的问题,我通过将一些片段事务代码从 onResume() 移动到 onStart() 来解决。

更准确地说:我的应用是一个启动器。按下 Android Home 按钮后,用户可以选择一个启动器,直到记住他/她的决定。当此时“返回”时(例如通过点击灰色区域),应用程序崩溃了。

也许这对某人有帮助。

【讨论】:

【参考方案8】:

这发生在我身上,因为我从正在泄漏活动的子片段中调用 commit()。它将活动保留为属性,并且 onAttach(); 未更新旋转活动变量,因此我试图通过保留的 (setRetainInstance(true);) 片段来提交僵尸活动上的事务。

【讨论】:

【参考方案9】:

异常的原因是FragmentActivityAsyncTask的运行期间重新创建,并且之后在onPostExecute()中对之前销毁的FragmentActivity的访问。

问题是要获得对新FragmentActivity 的有效引用。 getActivity()findById() 或类似的东西都没有这种方法。这个论坛充满了这个问题的主题(例如搜索"Activity context in onPostExecute")。其中一些正在描述解决方法(直到现在我还没有找到好的解决方法)。

也许将服务用于我的目的会是一个更好的解决方案。

【讨论】:

【参考方案10】:

对于这个问题,有一个替代解决方案(不是最佳解决方案),但有效。使用标志你可以处理它,如下所示

/**
 * 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;
    .....

您可以在进行片段交易时检查此boolean 值。

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

【讨论】:

【参考方案11】:

这解决了我的问题: Kotlin 代码:

val fragmentTransaction = activity.supportFragmentManager.beginTransaction()
fragmentTransaction.add(dialogFragment, tag)
fragmentTransaction.commitAllowingStateLoss()

commitAllowingStateLoss()commit() 有何不同?

根据文档:

类似于commit(),但允许在保存活动状态后执行提交。 https://developer.android.com/reference/android/app/FragmentTransaction#commitAllowingStateLoss()

P.S:您可以显示片段对话框,也可以通过此方法加载片段。两者都适用。

【讨论】:

【参考方案12】:

物有所值;我在后台运行服务的应用程序上遇到此错误。其中一个必须向用户显示超时对话框。如果应用不再在前台运行,该对话框就是导致此错误的问题。

在我们的例子中,当应用程序处于后台时显示对话框没有用,因此我们只是跟踪它(布尔标记 onPause en onResume),然后仅在应用程序对用户真正可见时才显示对话框。

【讨论】:

【参考方案13】:

从支持库版本 24.0.0 开始,您可以调用 FragmentTransaction.commitNow() 方法同步提交此事务,而不是调用 commit() 后跟 executePendingTransactions()

【讨论】:

【参考方案14】:

解决方案 1: 覆盖onSaveInstanceState() 并删除其中的超级调用。

@Override
public void onSaveInstanceState(Bundle outState) 

解决方案 2: 覆盖onSaveInstanceState() 并在超级调用之前删除您的片段

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

【讨论】:

【参考方案15】:

当一个进程试图操作一个其onStop() 被调用的Activity 时,就会出现这个问题。它不一定与片段事务相关,还与 onBackPressed() 等其他方法相关。

除了 AsyncTask 之外,此类问题的另一个来源是总线模式订阅的错位。通常 Event Bus 或 RxBus 的订阅在 Activity 的 onCreate 时注册,在 onDestroy 时注销。如果一个新的 Activity 启动并发布了一个被前一个 Activity 的订阅者截获的事件,那么它可能会产生这个错误。如果发生这种情况,那么一种解决方案是将订阅注册和注销移至onStart()onStop()

【讨论】:

【参考方案16】:

我的应用程序有一个要在 3 秒内加载的片段,但是当第一个屏幕准备显示时,我按下主页按钮并继续运行它,它显示相同的错误,所以它编辑我的代码并且运行非常顺利:

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

注意:添加 commitAllowingStateLoss() 而不是 commit()

【讨论】:

【参考方案17】:

如果您在活动丢失其状态后提交任何片段事务,则会遇到 IllegalStateException - 活动不在前台。当您尝试在 AsyncTask 中或在网络请求之后提交任何片段时,通常会遇到这种情况。

为避免这种崩溃,您只需延迟任何片段事务,直到活动状态恢复。以下是它的完成方式

声明两个私有布尔变量

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;

现在在 onPostResume() 和 onPause 中,我们设置和取消设置布尔变量 isTransactionSafe。想法是仅在活动处于前台时才将交易标记为安全,这样就不会丢失状态。

/*
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();
    

到目前为止,我们所做的将从 IllegalStateException 中保存,但如果在活动移至后台后完成,我们的事务将丢失,有点像 commitAllowStateloss()。为了解决这个问题,我们有 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;
 

This article 非常详细地解释了遇到此异常的原因并比较了各种解决方法。强烈推荐

【讨论】:

我做了类似的事情,但我使用了生命周期并仅在至少恢复后才执行事务。在模拟器中工作正常,但在真实设备上它会崩溃。为什么在示例中使用生命周期?【参考方案18】:

我有同样的例外,我尝试了许多我在这个 *** 讨论中找到的 sn-p,但没有一个 sn-ps 对我有用。

但是我能够解决所有问题,我将与您分享解决方案:

在第一部分中:我尝试在 Activity 上显示 DialogFragment,但来自另一个 java 类。然后通过查看那个实例的属性,发现是一个旧的Activity实例,不是当前运行的Activity。 [更准确地说,我使用的是 socket.io,但我忘记了 socket.off("example",example) ......所以它附加到了一个旧的活动实例。 ]

在第二部分中:当我带着意图返回到 Activity 时,我试图在 Activity 中显示 DialogFragment,但是当我检查我的日志时,我发现当它试图显示 Activity 的片段时仍然不在 onStart 方法中,所以它崩溃了应用程序,因为它没有找到 Activity 类来显示它的片段。

一些提示:如果您没有使用旧的 Activity 实例来显示您的片段,请检查一些属性,或者在显示片段之前检查您的 Activity 生命周期并确保您处于 onStart 或 onResume在展示它之前。

我希望这些解释对您有所帮助。

【讨论】:

以上是关于java.lang.IllegalStateException:onSaveInstanceState 后无法执行此操作的主要内容,如果未能解决你的问题,请参考以下文章