142

アプリのサポートライブラリを使用しています。FragmentActivityでは、インターネットからデータをダウンロードするためにAsyncTaskを使用しています。onPreExecute()メソッドでフラグメントを追加し、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()メソッドがnullポインターを返すためです。

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を使用していると思います。しかし、なぜ?

4

18 に答える 18

98

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();
            }
        });
}
于 2013-01-06T03:20:38.840 に答える
56

OlegVaskevichに感謝します。のを使用して問題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();
            }
        }
于 2013-01-08T19:36:34.840 に答える
41

この質問に対する正解は次の方法だと思います。

public abstract int commitAllowingStateLoss ()

commit()と同様ですが、アクティビティの状態が保存された後にコミットを実行できます。アクティビティを後でその状態から復元する必要がある場合、コミットが失われる可能性があるため、これは危険です。したがって、これは、ユーザーのUI状態が予期せず変更されても問題がない場合にのみ使用する必要があります。

上記の説明は、この方法に関するものです。

protected void onSaveInstanceState(android.os.Bundle outState)

この問題は、デバイスがスリープ状態になったときに正確に発生します。

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

于 2013-06-15T04:32:11.087 に答える
28

短くて実用的なソリューション:

簡単な手順に従ってください:

ステップ1onSaveInstanceState :それぞれのフラグメントの状態をオーバーライドします。そして、そこからスーパーメソッドを削除します。

@Override
public void onSaveInstanceState(Bundle outState) {
}

ステップ2:whileフラグメント操作CommitAllowingStateLoss();の代わりに使用します。commit();

fragmentTransaction.commitAllowingStateLoss();
于 2014-09-05T14:27:53.427 に答える
12

isFinishing()フラグメントを表示する前に、アクティビティを確認してください。

例:

if(!isFinishing()) {
FragmentManager fm = getSupportFragmentManager();
            FragmentTransaction ft = fm.beginTransaction();
            DummyFragment dummyFragment = DummyFragment.newInstance();
            ft.add(R.id.dummy_fragment_layout, dummyFragment);
            ft.commitAllowingStateLoss();
}
于 2015-03-04T01:22:58.833 に答える
6

commitAllowingStateLoss()の代わりに 使用してくださいcommit()

使用commit()すると、状態が失われた場合に例外がスローされる可能性がありますが、状態がcommitAllowingStateLoss()失われることなくトランザクションが保存されるため、状態が失われた場合に例外がスローされることはありません。

于 2018-06-06T08:51:07.533 に答える
5

フラグメントトランザクションコードをからonResume()に移動することで修正した同様の問題がありましたonStart()

もっと正確に言うと、私のアプリはランチャーです。Androidのホームボタンを押した後、ユーザーは自分の決定が記憶されるまでランチャーを選択できます。この時点で「戻る」と(たとえば、灰色がかった領域をタップして)、アプリがクラッシュしました。

多分これは誰かを助けます。

于 2013-08-28T09:40:17.230 に答える
2

例外の理由は、FragmentActivityの実行時にの再作成と、後で破棄されAsyncTaskた前のへのアクセスです。FragmentActivityonPostExecute()

問題は、新しいへの有効な参照を取得することですFragmentActivity。このための方法getActivity()findById()、それに類似したものもありません。このフォーラムは、この問題に応じたスレッドでいっぱいです(例:検索"Activity context in onPostExecute")。それらのいくつかは回避策を説明しています(今まで私は良いものを見つけられませんでした)。

たぶん、私の目的のためにサービスを使用する方が良い解決策になるでしょう。

于 2013-01-07T23:01:24.803 に答える
2

それは私にとって起こりました、なぜなら私はcommit()活動を漏らしているサブフラグメントから呼び出していたからです。アクティビティをプロパティとして保持し、ローテーションアクティビティ変数はによって更新されなかったため、保持されたフラグメントonAttach();によってゾンビアクティビティのトランザクションをコミットしようとしました。(setRetainInstance(true);)

于 2013-08-09T16:21:10.900 に答える
2

この問題には1つの代替ソリューション(最良のソリューションではありません)がありますが、機能します。フラグを使用すると、以下のように処理できます

/**
 * 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();
    }
}
于 2017-05-04T09:32:23.590 に答える
2

これで私の問題は解決しました:Kotlinコード:

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

とはどうcommitAllowingStateLoss()違うのcommit()

ドキュメントによると:

同様commit()ですが、アクティビティの状態が保存された後にコミットを実行できます。 https://developer.android.com/reference/android/app/FragmentTransaction#commitAllowingStateLoss()

PS:フラグメントダイアログを表示したり、この方法でフラグメントをロードしたりできます。両方に適用できます。

于 2020-07-03T17:22:40.560 に答える
1

それが価値があるもののために; バックグラウンドでサービスを実行しているアプリでこのエラーが発生しました。それらの1つでは、タイムアウトダイアログをユーザーに表示する必要がありました。そのダイアログは、アプリがフォアグラウンドで実行されなくなった場合にこのエラーを引き起こす問題でした。

私たちの場合、アプリがバックグラウンドにあるときにダイアログを表示することは役に立たなかったので、それを追跡し(ブール値のフラグが付けられたonPause en onResume)、アプリが実際にユーザーに表示されているときにのみダイアログを表示します。

于 2013-05-03T07:44:44.677 に答える
1

解決策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);
}
于 2016-05-27T08:07:01.747 に答える
1

サポートライブラリバージョン24.0.0以降では、後FragmentTransaction.commitNow()に呼び出す代わりに、このトランザクションを同期的にコミットするメソッドを呼び出すことができます。commit()executePendingTransactions()

于 2016-08-29T20:24:02.183 に答える
1

onStop()この問題は、プロセスが呼び出されたアクティビティを操作しようとしたときに発生します。必ずしもフラグメントトランザクションに関連付けられているわけではなく、onBackPressed()などの他のメソッドにも関連付けられています。

AsyncTaskに加えて、このような問題のもう1つの原因は、バスパターンのサブスクリプションの置き忘れです。通常、イベントバスまたはRxBusのサブスクリプションは、アクティビティのonCreate中に登録され、onDestroyで登録解除されます。新しいアクティビティが開始され、前のアクティビティのサブスクライバーによってインターセプトされたイベントが公開されると、このエラーが発生する可能性があります。これが発生した場合、1つの解決策は、サブスクリプションの登録と登録解除をとに移動することonStart()ですonStop()

于 2017-01-02T09:19:37.947 に答える
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();
        }
    });

注: commit()の代わりにcommitAllowingStateLoss()を追加してください

于 2015-06-24T02:23:55.697 に答える
0

アクティビティが状態を失った後にフラグメントトランザクションをコミットすると、IllegalStateExceptionが発生します-アクティビティはフォアグラウンドではありません。これは、AsyncTaskでフラグメントをコミットしようとしたとき、またはネットワーク要求の後によく発生します。

このクラッシュを回避するには、アクティビティの状態が復元されるまでフラグメントトランザクションを遅らせる必要があります。以下はそれがどのように行われるかです

2つのプライベートブール変数を宣言します

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

この記事では、この例外が発生する理由を詳細に説明し、さまざまな方法を比較して解決します。強くお勧めします

于 2018-07-01T10:28:12.130 に答える
0

同じ例外があり、このスタックオーバーフローのディスカッションで見つけた多くのスニペットを試しましたが、スニペットは機能しませんでした。

しかし、私はすべての問題を解決することができました、私はあなたと解決策を共有します:

  • 最初の部分:アクティビティでDialogFragmentを表示しようとしましたが、別のJavaクラスからのものです。次に、そのインスタンスの属性を確認したところ、それはアクティビティの古いインスタンスであり、現在実行中のアクティビティではないことがわかりました。[より正確には、socket.ioを使用していましたが、socket.off( "example"、example)を実行するのを忘れていたため、アクティビティの古いインスタンスにアタッチされていました。]

  • 2番目の部分:意図的に戻ってきたときにアクティビティでDialogFragmentを表示しようとしましたが、ログを確認したところ、フラグメントを表示しようとしたときに、アクティビティがまだonStartメソッドにないことがわかりました、そのため、フラグメントを表示するActivityクラスが見つからなかったため、アプリがクラッシュしました。

いくつかのヒント:フラグメントを表示しようとしているアクティビティの古いインスタンスを使用していない場合は、いくつかの属性を確認するか、フラグメントを表示する前にアクティビティのライフサイクルを確認し、表示する前にonStartまたはonResumeにいることを確認してください。

それらの説明がお役に立てば幸いです。

于 2018-07-26T12:53:06.750 に答える