Saya menggunakan pustaka dukungan untuk aplikasi saya. Dalam FragmentActivity saya, saya menggunakan AsyncTask untuk mengunduh data dari internet. Dalam metode onPreExecute () saya menambahkan Fragment dan dalam metode onPostExecute () saya menghapusnya lagi. Ketika orientasi diubah di antara keduanya, saya mendapatkan pengecualian yang disebutkan di atas. Silakan lihat detailnya:
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");
...
}
Saya mendapatkan LogCut berikut:
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)
Di utas lain tentang masalah serupa, alasannya tampaknya karena metode onPostExecute dipanggil sebelum metode onResume () dipanggil. Tapi saya mendapatkan pengecualian meskipun onResume () dipanggil sebelumnya.
Apakah ada yang tahu apa yang salah?
Aktivitasnya terlihat seperti ini:
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);
}
}
Saat menggunakan commitAllowingStateLoss () saya mendapatkan pengecualian berikut:
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)
Saya mendapatkan IllegalStateExeption yang sama ketika saya menerapkan AsynTask sebagai berikut, karena metode findFragmentById () mengembalikan pointer nol.
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();
}
Pada langkah selanjutnya saya menggunakan handler untuk menambah dan menghapus DummyFragment. Selain itu saya telah menambahkan beberapa keluaran debug.
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();
}
});
Saya mendapatkan LogCut berikut:
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)
Di onPreExecute () FriendListFragment memiliki id = 0x7f0a0002. Di dalam handler, DummyFragment dibuat dengan id = 0x7f0a0004. Dalam onPostExecute () kedua ID tersebut adalah null. Di onPreExecute (), alamat MyFragmentActivity adalah 45e38358. tetapi di onPostExecute () nilainya null. Namun di kedua metode, alamat FragmentManager adalah 45e384a8. Saya kira onPostExecute menggunakan FragmentManager yang tidak valid. Tapi kenapa?
Jawaban:
Anda harus melakukan transaksi
Handler
sebagai berikut:@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(); } }); }
sumber
private static WeakReference<FragmentActivity> mActivity = null;
WeakReference
mencegah Anda membocorkan aktivitas ... Anda perlu memanggilmActivity.get()
untuk benar-benar mendapatkan instance, dan akan bernilai null jika aktivitas dimusnahkan. Untuk memperbaruinya, Anda perlu menulismActivity = new WeakReference<FragmentActivity>(this);
- tempat yang bagusonCreate()
- yang akan memperbarui referensi.Terima kasih Oleg Vaskevich. Menggunakan salah satu
WeakReference
dari masalah yangFragmentActivity
dipecahkan. Kode saya terlihat sebagai berikut sekarang: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(); } }
sumber
MyFragmentActivity mActivity = this ?
With out static & WeakReferenceSaya yakin jawaban yang benar untuk pertanyaan ini adalah metode berikut.
public abstract int commitAllowingStateLoss ()
Uraian di atas berkaitan dengan metode ini.
protected void onSaveInstanceState(android.os.Bundle outState)
Masalah ini terjadi justru saat perangkat tidur.
http://developer.android.com/reference/android/app/FragmentTransaction.html
sumber
Solusi Singkat Dan Bekerja:
Ikuti Langkah Sederhana:
Langkah 1 : Ganti
onSaveInstanceState
status di masing-masing fragmen. Dan hapus metode super darinya.@Override public void onSaveInstanceState(Bundle outState) { }
Langkah 2 : Gunakan
CommitAllowingStateLoss();
sebagai ganticommit();
while operasi fragmen.fragmentTransaction.commitAllowingStateLoss();
sumber
Periksa apakah aktivitas tersebut
isFinishing()
sebelum menampilkan fragmen.Contoh:
sumber
Saya memiliki masalah serupa yang saya perbaiki dengan memindahkan beberapa kode transaksi fragmen dari
onResume()
ke dalamonStart()
.Lebih tepatnya: Aplikasi saya adalah peluncur. Setelah menekan tombol Beranda Android, pengguna dapat memilih peluncur sampai keputusannya diingat. Saat "kembali" pada titik ini (misalnya dengan mengetuk di area abu-abu) aplikasi macet.
Mungkin ini membantu seseorang.
sumber
Gunakan
commitAllowingStateLoss()
sebagai ganticommit()
.Saat digunakan
commit()
akan memunculkan eksepsi jika terjadi kerugian negara tetapicommitAllowingStateLoss()
menyimpan transaksi tanpa kerugian negara sehingga tidak memunculkan eksepsi jika terjadi kerugian negara.sumber
Itu terjadi pada saya, karena saya memanggil
commit()
dari subfragmen yang membocorkan aktivitas. Itu menyimpan aktivitas sebagai properti dan pada variabel aktivitas rotasi tidak diperbarui olehonAttach();
Jadi saya mencoba melakukan transaksi pada Aktivitas zombie dengan(setRetainInstance(true);)
fragmen yang dipertahankan .sumber
Alasan pengecualian adalah pembuatan ulang
FragmentActivity
selama runtimeAsyncTask
dan akses ke yang sebelumnya, dimusnahkanFragmentActivity
dalamonPostExecute()
sesudahnya.Masalahnya adalah mendapatkan referensi yang valid ke yang baru
FragmentActivity
. Tidak ada metode untuk ini,getActivity()
ataufindById()
atau yang serupa. Forum ini penuh dengan utas tentang masalah ini (mis. Cari"Activity context in onPostExecute"
). Beberapa dari mereka menjelaskan solusi (sampai sekarang saya tidak menemukan solusi yang bagus).Mungkin ini akan menjadi solusi yang lebih baik untuk menggunakan Layanan untuk tujuan saya.
sumber
Ada satu solusi alternatif (BUKAN solusi terbaik) untuk masalah ini, tetapi berhasil. Menggunakan flag Anda bisa mengatasinya, seperti di bawah ini
/** * 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; ..... }
Dan Anda dapat memeriksa
boolean
nilai ini saat melakukan transaksi fragmen.private void fragmentReplace(Fragment fragment, String fragmentTag){ if (!isOnSaveInstanceStateCalled) { getSupportFragmentManager() .beginTransaction() .replace(R.id.layout_container, fragment, fragmentTag) .commit(); } }
sumber
Untuk apa nilainya; Saya mengalami kesalahan ini pada aplikasi yang menjalankan layanan di latar belakang. Di salah satunya, dialog batas waktu harus ditampilkan kepada pengguna. Dialog itu adalah masalah yang menyebabkan kesalahan ini jika aplikasi tidak lagi berjalan di latar depan.
Dalam kasus kami, menampilkan dialog tidak berguna saat aplikasi berada di latar belakang jadi kami terus melacaknya (boolean ditandai onPause en onResume) dan kemudian hanya menampilkan dialog saat aplikasi benar-benar terlihat oleh pengguna.
sumber
Solusi 1: Timpa
onSaveInstanceState()
dan hapus panggilan super di dalamnya.@Override public void onSaveInstanceState(Bundle outState) { }
Solusi 2: Timpa
onSaveInstanceState()
dan hapus fragmen Anda sebelum panggilan super@Override public void onSaveInstanceState(Bundle outState) { // TODO: Add code to remove fragment here super.onSaveInstanceState(outState); }
sumber
Masalah ini terjadi ketika suatu proses mencoba memanipulasi Aktivitas yang
onStop()
telah dipanggil. Ini tidak selalu terkait dengan transaksi fragmen tetapi juga metode lain seperti onBackPressed ().Selain AsyncTask, sumber masalah lainnya adalah kesalahan penempatan langganan pola bus. Biasanya langganan Event Bus atau RxBus terdaftar selama onCreate Aktivitas dan didaftarkan di onDestroy. Jika Aktivitas baru dimulai dan menerbitkan acara yang dicegat oleh pelanggan dari Aktivitas sebelumnya, maka hal itu mungkin menghasilkan kesalahan ini. Jika ini terjadi, salah satu solusinya adalah dengan memindahkan pendaftaran langganan dan pembatalan pendaftaran ke
onStart()
danonStop()
.sumber
Ini memecahkan masalah saya: Kode Kotlin:
val fragmentTransaction = activity.supportFragmentManager.beginTransaction() fragmentTransaction.add(dialogFragment, tag) fragmentTransaction.commitAllowingStateLoss()
Apa
commitAllowingStateLoss()
bedanya dengancommit()
?Sesuai dokumentasi:
Suka
commit()
tetapi mengizinkan komit untuk dieksekusi setelah status aktivitas disimpan. https://developer.android.com/reference/android/app/FragmentTransaction#commitAllowingStateLoss ()PS: Anda dapat menampilkan Dialog Fragmen atau dapat memuat fragmen dengan metode ini. Berlaku untuk keduanya.
sumber
Aplikasi saya memiliki fragmen untuk dimuat dalam 3 detik, tetapi ketika layar pertama bersiap untuk ditampilkan, saya menekan tombol beranda dan melanjutkan menjalankannya, itu menunjukkan kesalahan yang sama, jadi Ini mengedit kode saya dan itu berjalan sangat lancar:
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(); } });
CATATAN: tambahkan commitAllowingStateLoss () daripada commit ()
sumber
Mulai dari pustaka dukungan versi 24.0.0, Anda dapat memanggil
FragmentTransaction.commitNow()
metode yang melakukan transaksi ini secara sinkron alih-alih memanggilcommit()
diikuti olehexecutePendingTransactions()
sumber
IllegalStateException ditemui jika Anda melakukan transaksi fragmen apa pun setelah aktivitas kehilangan statusnya- Aktivitas tidak berada di latar depan. Ini biasanya ditemui saat Anda mencoba memasukkan fragmen apa pun di AsyncTask atau setelah permintaan jaringan.
Untuk menghindari crash ini, Anda hanya perlu menunda transaksi fragmen apa pun hingga status aktivitas dipulihkan. Berikut ini adalah cara melakukannya
Deklarasikan dua variabel boolean privat
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;
Sekarang di onPostResume () dan onPause kita menyetel dan menghapus variabel boolean isTransactionSafe. Idealnya adalah menandai transaksi aman hanya jika aktivitas berada di latar depan sehingga tidak ada peluang stateloss.
/* 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(); } }
Apa yang telah kita lakukan sejauh ini akan menyelamatkan dari IllegalStateException tetapi transaksi kita akan hilang jika dilakukan setelah aktivitas berpindah ke latar belakang, seperti commitAllowStateloss (). Untuk membantu itu kami memiliki variabel boolean 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; } }
Artikel ini menjelaskan secara cukup rinci mengapa pengecualian ini ditemui dan membandingkan berbagai metode untuk mengatasinya. Sangat dianjurkan
sumber
Saya memiliki pengecualian yang sama dan saya mencoba banyak cuplikan yang saya temukan di sini pada diskusi stackoverflow ini, tetapi tidak ada cuplikan yang berhasil untuk saya.
Tetapi saya dapat menyelesaikan semua masalah, saya akan berbagi dengan Anda solusinya:
Di bagian Pertama: Saya mencoba menampilkan DialogFragment pada Aktivitas tetapi dari kelas java lain. Kemudian dengan memeriksa atribut dari instance itu, saya menemukan bahwa itu adalah instance lama dari Activity, itu bukan Activity yang sedang berjalan. [Lebih tepatnya saya menggunakan socket.io, dan saya lupa melakukan socket.off ("contoh", contoh) ... jadi itu dilampirkan ke instance lama dari aktivitas. ]
Di bagian Kedua: Saya mencoba menampilkan DialogFragment dalam Aktivitas ketika saya kembali ke sana dengan maksud, tetapi ketika saya memeriksa log saya, saya melihat bahwa ketika mencoba menampilkan fragmen, aktivitas masih belum dalam metode onStart , sehingga membuat aplikasi crash karena tidak menemukan kelas Activity untuk menampilkan fragmen di atasnya.
Beberapa tip: periksa dengan beberapa atribut jika Anda tidak menggunakan instance lama dari aktivitas Anda yang ingin Anda tampilkan fragmennya, atau periksa daur hidup aktivitas Anda sebelum menampilkan fragmen dan pastikan Anda berada di onStart atau onResume sebelum menampilkannya .
Saya harap penjelasan itu akan membantu Anda.
sumber