java.lang.IllegalStateException : onSaveInstanceState 후에이 조치를 수행 할 수 없습니다.


135

내 앱에 지원 라이브러리를 사용하고 있습니다. 내 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 ()이 전에 호출되었지만 예외가 발생합니다.

누군가가 무엇이 잘못되었는지 알고 있습니까?

활동은 다음과 같습니다.

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)

findFragmentById () 메서드가 null 포인터를 반환하기 때문에 다음과 같이 AsynTask를 구현할 때 동일한 IllegalStateExeption을 얻습니다.

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를 사용한다고 생각합니다. 그런데 왜?


1
이 문제가 한 번 발생하고 커밋을 commitAllowingStateLoss ()로 바꿔서 고쳤습니다.
Cata

나는 이미 이것을 시도했지만 성공하지 못했습니다. LogCat에 따르면 조각은 올바른 상태에 있어야합니다.
samo

활동 코드를 게시 할 수 있습니까?
Robert Estivill

commitAllowingStateLoss ()를 사용하면 다른 예외가 발생합니다 (위 참조).
samo

6
여전히 솔루션을 찾고있는 분들을 위해 ... 자세한 정보는이 주제에 대한이 블로그 게시물 을 참조하십시오.
Alex Lockwood

답변:


97

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

12
도움이되지 않습니다. 동작은 이전과 동일합니다.
samo

@samo 문제를 해결할 수 있었습니까? 비슷한 상황에 처해 있습니다
Lisa Anne

3
이 코드를 고려하십시오 :private static WeakReference<FragmentActivity> mActivity = null;
Oleg Vaskevich

2
간단히 말해서 WeakReference액티비티가 누출되는 것을 방지합니다 ... mActivity.get()실제로 인스턴스를 얻으려면 호출해야 하며 액티비티가 파괴되면 null이됩니다. 업데이트하려면 참조를 업데이트 할 수 mActivity = new WeakReference<FragmentActivity>(this);있는 좋은 위치 에 작성해야합니다 onCreate().
Oleg Vaskevich

107
여전히 솔루션을 찾고있는 분들을 위해 ... 자세한 정보는이 주제에 대한이 블로그 게시물 을 참조하십시오.
Alex Lockwood 23.07.

55

감사합니다 Oleg Vaskevich. 사용 WeakReference의 것은 FragmentActivity문제를 해결했다. 내 코드는 다음과 같습니다.

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

약한 참조 아이디어는 실제로 매우 똑똑한 아이디어이므로 필요한 경우 객체를 쉽게 가비지 수집 할 수 있습니다. 엄지 손가락 사모!
Jimmy Ilenloa

왜 static이 여기에 사용됩니까? 내가 사용하는 경우 MyFragmentActivity mActivity = this ?함께 정적 및 WeakReference를
바라 스

정적 참조는 매우 나쁜 엔지니어링입니다. 비동기 작업을 수명주기에 묶고 필요할 때 취소해야합니다.
breakline

38

이 질문에 대한 정답은 다음과 같은 방법이라고 생각합니다.

public abstract int commitAllowingStateLoss ()

commit ()과 유사하지만 활동 상태가 저장된 후에 커밋을 실행할 수 있습니다. 활동을 나중에 상태에서 복원해야하는 경우 커미트가 유실 될 수 있으므로 이는 위험합니다. 따라서 UI 상태가 사용자에게 예기치 않게 변경 될 수있는 경우에만 사용해야합니다.

상기 설명은이 방법에 관한 것이다.

protected void onSaveInstanceState(android.os.Bundle outState)

이 문제는 장치가 절전 모드로 전환 될 때 정확하게 발생합니다.

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


25

짧고 효과적인 해결책 :

간단한 단계를 따르십시오 :

1 단계 : onSaveInstanceState각 조각의 상태를 무시 합니다. 그리고 슈퍼 메소드를 제거하십시오.

@Override
public void onSaveInstanceState(Bundle outState) {
}

2 단계 : 조각화 작업 CommitAllowingStateLoss();대신 사용하십시오 commit();.

fragmentTransaction.commitAllowingStateLoss();

2
감사. 이것은 저에게 효과적이지만 최선의 해결책은 아닙니다.
wendigo

2
수퍼 메소드를 제거하면 프래그먼트 상태 저장이 비활성화됩니다.
Juan Mendez

1
감사합니다. lot.it가 예외를 생성하고 있었으므로이 솔루션은 잘 작동했습니다.
Deepak

11

isFinishing()조각을 표시하기 전에 활동을 확인하십시오 .

예:

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

5

조각 트랜잭션 코드를에서 onResume()로 이동하여 비슷한 문제가 발생 했습니다 onStart().

더 정확하게 말하면 : 내 앱은 실행기입니다. 안드로이드 홈 버튼을 누른 후, 사용자는 자신의 결정이 기억 될 때까지 런처를 선택할 수 있습니다. 이 시점에서 "예"로 돌아 가면 (예 : 회색 영역을 탭하여) 앱이 다운되었습니다.

어쩌면 이것은 누군가를 도울 수 있습니다.


4

commitAllowingStateLoss()대신에 사용하십시오 commit().

사용 commit()하면 상태 손실이 발생하면 예외를 throw 할 수 있지만 commitAllowingStateLoss()상태 손실없이 트랜잭션을 저장하므로 상태 손실이 발생하면 예외가 발생하지 않습니다.


2

commit()누수 된 하위 조각 에서 호출했기 때문에 그 일이 일어났습니다 . 그것은 활동을 속성으로 유지하고 회전 활동 변수에 의해 업데이트되지 않았으므로 조각 onAttach();을 유지하여 좀비 활동에서 트랜잭션을 커밋하려고했습니다 (setRetainInstance(true);).


2

예외의 이유 FragmentActivity는 런타임 중에 AsyncTask및 이전에 대한 액세스를 다시 작성 FragmentActivity하여 onPostExecute()나중에 파괴 되었기 때문 입니다 .

문제는 new에 대한 유효한 참조를 얻는 것 FragmentActivity입니다. 이것에 대한 방법도 getActivity()없고 findById()비슷한 것도 없습니다 . 이 포럼은이 문제에 따른 스레드로 가득합니다 (예 : 검색 "Activity context in onPostExecute"). 그들 중 일부는 해결 방법을 설명하고 있습니다 (지금은 좋은 것을 찾지 못했습니다).

아마도 내 목적으로 서비스를 사용하는 것이 더 나은 솔루션 일 것입니다.


2

이 문제에 대한 하나의 대체 솔루션 (최상의 솔루션은 아님)이 있지만 작동합니다. 플래그를 사용하면 아래와 같이 처리 할 수 ​​있습니다

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

1

가치있는 일을 위해; 백그라운드에서 서비스를 실행하는 앱 에서이 오류가 발생했습니다. 그중 하나에서 시간 초과 대화 상자가 사용자에게 표시되어야했습니다. 앱이 더 이상 포 그라운드에서 실행되지 않는 경우 해당 대화 상자에서이 오류가 발생했습니다.

우리의 경우 앱이 백그라운드에있을 때 대화 상자가 유용하지 않았으므로 우리는 그 정보를 추적하고 (boolean onPause en onResume으로 플래그 지정) 앱이 실제로 사용자에게 표시 될 때만 대화 상자를 표시합니다.


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

1

이 문제점은 프로세스가 onStop()호출 된 활동을 조작하려고 할 때 발생합니다 . 반드시 조각 트랜잭션과 관련이있는 것은 아니지만 onBackPressed ()와 같은 다른 메소드도 있습니다.

AsyncTask 외에도 이러한 문제점의 또 다른 원인은 버스 패턴 구독이 잘못 배치 된 것입니다. 일반적으로 이벤트 버스 또는 RxBus의 구독은 활동의 onCreate 및 onDestroy에서 등록 취소 중에 등록됩니다. 새 활동이 시작되고 이전 활동의 구독자가 인터셉트 한 이벤트를 공개하면이 오류가 발생할 수 있습니다. 이 후 발생하면 하나 개의 솔루션 구독 등록에 대한 등록 취소 이동하는 것입니다 onStart()onStop().


1

이것은 내 문제를 해결했습니다 : Kotlin Code :

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

어떻게 commitAllowingStateLoss()다르다 commit()?

설명서에 따라 :

마찬가지로 commit()그러나 허용은 활동의 상태를 저장 한 후 실행되는 커밋합니다. https://developer.android.com/reference/android/app/FragmentTransaction#commitAllowingStateLoss ()

추신 : 조각 대화 상자를 표시 하거나이 방법으로 조각을로드 할 수 있습니다. 두 가지 모두에 적용됩니다.


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 ()를 추가하십시오 .


0

지원 라이브러리 버전에서 시작 24.0.0 당신이 호출 할 수 FragmentTransaction.commitNow()호출하는 대신 동 기적으로 트랜잭션을 커밋 방법 commit()다음을executePendingTransactions()


0

활동이 상태를 잃은 후 조각 트랜잭션을 커밋하면 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;
 }
}

이 기사 는이 예외가 발생한 이유를 상세하게 설명하고이를 해결하기 위해 다양한 방법을 비교합니다. 추천


0

나는 같은 예외가 있었고이 stackoverflow 토론에서 여기에서 찾은 많은 스 니펫을 시도했지만 스 니펫은 나를 위해 일하지 않았습니다.

그러나 모든 문제를 해결할 수 있었으며 해결책을 알려 드리겠습니다.

  • 첫 번째 부분 : Activity에 DialogFragment를 표시하려고했지만 다른 Java 클래스에서 DialogFragment를 표시하려고했습니다. 그런 다음 해당 인스턴스의 속성을 확인하여 활동의 오래된 인스턴스라는 것을 알았습니다. 현재 실행중인 활동이 아닙니다. [더 정확하게는 socket.io를 사용하고 있었고 socket.off ( "example", example) ...을 수행하는 것을 잊어 버렸습니다. 그래서 활동의 오래된 인스턴스에 연결되었습니다. ]

  • 두 번째 부분 : 의도로 다시 돌아올 때 Activity에 DialogFragment를 표시하려고했지만 로그를 확인했을 때 조각을 표시하려고 할 때 활동이 여전히 onStart 메소드에 있지 않은 것을 보았습니다. 따라서 조각을 표시 할 Activity 클래스를 찾지 못해 앱이 중단되었습니다.

몇 가지 팁 : 조각을 표시하려는 활동의 이전 인스턴스를 사용하지 않는 경우 일부 속성을 확인하거나 조각을 표시하기 전에 활동 수명주기를 확인하고 조각을 표시하기 전에 onStart 또는 onResume에 있는지 확인하십시오. .

그 설명이 도움이 되길 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.