首页 文章

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

提问于
浏览
129

我正在为我的应用程序使用支持库 . 在我的FragmentActivity中,我使用AsyncTask从Internet下载数据 . 在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(),我也会得到异常 .

有人知道什么是错的吗?

活动看起来像这样:

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

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

17 回答

  • 0

    Solution 1: 覆盖 onSaveInstanceState() 并删除其中的超级电话 .

    @Override
    public void onSaveInstanceState(Bundle outState) {
    }
    

    Solution 2: 覆盖 onSaveInstanceState() 并在超级呼叫之前删除您的片段

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

    那件事发生在我身上,因为我从子片段中调用了 commit() 这是一个泄漏的活动 . 它将活动保持为属性并且循环活动变量未被 onAttach(); 更新所以我试图通过保留 (setRetainInstance(true);) 片段在僵尸活动上提交事务 .

  • 2

    您应该在 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();
                }
            });
    }
    
  • 53

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

    public abstract int commitAllowingStateLoss ()
    

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

    以上描述涉及该方法 .

    protected void onSaveInstanceState(android.os.Bundle outState)
    

    当设备进入睡眠状态时,会出现此问题 .

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

  • 1

    短而有效的解决方案:

    遵循简单步骤:

    Step 1 :在相应的片段中覆盖 onSaveInstanceState 状态 . 并从中删除超级方法 .

    @Override
    public void onSaveInstanceState(Bundle outState) {
    }
    

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

    fragmentTransaction.commitAllowingStateLoss();
    
  • 35

    使用 commitAllowingStateLoss() 而不是 commit() .

    当你使用 commit() 时,如果发生状态丢失,它将抛出一个异常,但 commitAllowingStateLoss() 保存事务而没有状态丢失,因此如果发生状态丢失,则不会抛出异常 .

  • 2

    异常的原因是在 AsyncTask 的运行时期间重新创建 FragmentActivity 并且之后访问 onPostExecute() 中的前一个,销毁 FragmentActivity .

    问题是获得对新 FragmentActivity 的有效引用 . 没有任何方法既不是 getActivity() 也不是 findById() 或类似的东西 . 根据这个问题,这个论坛充满了线程(例如搜索 "Activity context in onPostExecute" ) . 他们中的一些人正在描述解决方法(直到现在我找不到一个好的解决方法) .

    也许这是一个更好的解决方案,为我的目的使用服务 .

  • 5

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

    在我们的情况下显示当app在后台时对话框没有用,所以我们只是跟踪它(boolean标记onPause en onResume)然后只显示用户实际可见应用程序时的对话框 .

  • 24

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

    Example:

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

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

  • 0

    我有同样的例外,我尝试了很多我在这个stackoverflow讨论中找到的片段,但没有片段对我有用 .

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

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

    • 在第二部分中:我试图在一个Activity中显示一个DialogFragment,当我以一个意图回到它时,但当我检查我的日志时,我看到当它试图显示片段时,活动仍未在onStart中方法,因此它崩溃了应用程序,因为它没有找到Activity类来显示它上面的片段 .

    一些提示:如果不是,请检查一些属性使用您正在尝试显示片段的旧活动实例,或在显示片段之前检查您的活动生命周期,并确保在显示片段之前使用onStart或onResume .

    我希望这些解释对你有所帮助 .

  • 1

    如果在活动失去状态后提交任何片段事务,则会遇到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 . 想法是仅在活动处于前景时标记trasnsaction安全,因此没有状态损失的可能性 .

    /*
    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详细解释了为什么遇到此异常并比较各种方法来解决它 . 强烈推荐

  • 0

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

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

    也许这有助于某人 .

  • 1

    谢谢Oleg Vaskevich . 使用 WeakReferenceFragmentActivity 解决了这个问题 . 我的代码现在看起来如下:

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

    当进程尝试操作已调用 onStop() 的活动时,会发生此问题 . 它不一定与片段事务有关,也与onBackPressed()等其他方法有关 .

    除了AsyncTask之外,此类问题的另一个原因是总线模式的错位's subscription. Usually Event Bus or RxBus' s订阅在Activity的onCreate期间注册并在onDestroy中取消注册 . 如果新的Activity启动并发布由前一个Activity的订阅者截获的事件,则可能会产生此错误 . 如果发生这种情况,那么一种解决方案是将订阅注册和注销移至 onStart()onStop() .

  • 2

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

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

    我的应用程序有一个片段加载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();
            }
        });
    

    NOTE: 添加commitAllowingStateLoss()而不是commit()

相关问题