Saya memiliki aplikasi Android Live, dan dari pasar saya telah menerima jejak stack berikut dan saya tidak tahu mengapa hal ini terjadi karena tidak terjadi dalam kode aplikasi tetapi disebabkan oleh beberapa atau peristiwa lain dari aplikasi (asumsi)
Saya tidak menggunakan Fragmen, masih ada referensi FragmentManager. Jika ada orang yang dapat menyoroti fakta-fakta tersembunyi untuk menghindari masalah seperti ini:
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1109)
at android.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:399)
at android.app.Activity.onBackPressed(Activity.java:2066)
at android.app.Activity.onKeyDown(Activity.java:1962)
at android.view.KeyEvent.dispatch(KeyEvent.java:2482)
at android.app.Activity.dispatchKeyEvent(Activity.java:2274)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1668)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchKeyEvent(PhoneWindow.java:1720)
at com.android.internal.policy.impl.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1258)
at android.app.Activity.dispatchKeyEvent(Activity.java:2269)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1668)
at android.view.ViewRoot.deliverKeyEventPostIme(ViewRoot.java:2851)
at android.view.ViewRoot.handleFinishedEvent(ViewRoot.java:2824)
at android.view.ViewRoot.handleMessage(ViewRoot.java:2011)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:132)
at android.app.ActivityThread.main(ActivityThread.java:4025)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:491)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
at dalvik.system.NativeStart.main(Native Method)
Jawaban:
Ini adalah bug paling bodoh yang saya temui sejauh ini. Saya memiliki
Fragment
aplikasi yang berfungsi dengan baik untuk API <11 , danForce Closing
pada API> 11 .Saya benar-benar tidak tahu apa yang mereka ubah di dalam
Activity
siklus hidup dalam panggilan untuksaveInstance
, tetapi saya di sini adalah bagaimana saya memecahkan ini:Saya hanya tidak menelepon
.super()
dan semuanya bekerja dengan baik. Saya harap ini akan menghemat waktu Anda.EDIT: setelah beberapa penelitian lebih lanjut, ini adalah bug yang dikenal dalam paket dukungan.
Jika Anda perlu menyimpan instance, dan menambahkan sesuatu ke Anda,
outState
Bundle
Anda dapat menggunakan yang berikut:EDIT2: ini juga dapat terjadi jika Anda mencoba melakukan transaksi setelah
Activity
latar belakang Anda hilang. Untuk menghindari ini, Anda harus menggunakancommitAllowingStateLoss()
EDIT3: Solusi di atas memperbaiki masalah di perpustakaan support.v4 awal dari apa yang saya ingat. Tetapi jika Anda masih memiliki masalah dengan ini, Anda HARUS juga membaca blog @AlexLockwood : Transaksi Fragmen & Aktivitas Kehilangan Negara
Ringkasan dari posting blog (tapi saya sangat menyarankan Anda untuk membacanya):
commit()
bertransaksi setelahonPause()
pada pra-Honeycomb, danonStop()
pada pasca-HoneycombActivity
metode siklus hidup. GunakanonCreate()
,onResumeFragments()
danonPostResume()
commitAllowingStateLoss()
hanya sebagai pilihan terakhirsumber
commitAllowingStateLoss()
hanya menghindari pengecualian. Itu tidak melindungi aplikasi Anda dari kehilangan kondisi tidak disengaja. Lihat posting blog ini .Mencari di kode sumber Android tentang apa yang menyebabkan masalah ini memberikan bahwa flag mStateSaved di
FragmentManagerImpl
kelas (contoh tersedia di Activity) memiliki nilai true. Ini disetel ke true ketika tumpukan belakang disimpan (saveAllState) saat panggilan dariActivity#onSaveInstanceState
. Setelah itu panggilan dari ActivityThread tidak mengatur ulang flag ini menggunakan metode reset yang tersedia dariFragmentManagerImpl#noteStateNotSaved()
dandispatch()
.Cara saya melihatnya ada beberapa perbaikan yang tersedia, tergantung pada apa yang dilakukan dan digunakan aplikasi Anda:
Cara yang baik
Sebelum hal lain: Saya akan mengiklankan artikel Alex Lockwood . Lalu, dari apa yang telah saya lakukan sejauh ini:
Untuk fragmen dan aktivitas yang tidak perlu menyimpan informasi status apa pun, hubungi commitAllowStateLoss . Diambil dari dokumentasi:
Tepat setelah transaksi dilakukan (Anda baru saja menelepon
commit()
), lakukan panggilan keFragmentManager.executePendingTransactions()
.Cara yang tidak disarankan:
Seperti Ovidiu Latcu yang disebutkan di atas, jangan menelepon
super.onSaveInstanceState()
. Tetapi ini berarti Anda akan kehilangan seluruh status aktivitas Anda bersama dengan fragmen.Timpa
onBackPressed
dan hanya ada panggilanfinish()
. Ini seharusnya OK jika aplikasi Anda tidak menggunakan Fragmen API; seperti disuper.onBackPressed
sana ada panggilan untukFragmentManager#popBackStackImmediate()
.Jika Anda menggunakan kedua API Fragmen dan status aktivitas Anda penting / vital, maka Anda dapat mencoba menelepon menggunakan API refleksi
FragmentManagerImpl#noteStateNotSaved()
. Tapi ini peretasan, atau bisa dikatakan itu solusi. Saya tidak suka, tetapi dalam kasus saya ini cukup dapat diterima karena saya memiliki kode dari aplikasi lawas yang menggunakan kode usang (TabActivity
dan secara implisitLocalActivityManager
).Di bawah ini adalah kode yang menggunakan refleksi:
Bersulang!
sumber
Pengecualian seperti itu akan terjadi jika Anda mencoba melakukan transisi fragmen setelah aktivitas fragmen Anda
onSaveInstanceState()
dipanggil.Salah satu alasan ini bisa terjadi, adalah jika Anda membiarkan
AsyncTask
(atauThread
) menjalankan ketika suatu aktivitas dihentikan.Setiap transisi setelah
onSaveInstanceState()
dipanggil dapat berpotensi hilang jika sistem mengklaim kembali aktivitas untuk sumber daya dan membuatnya kembali nanti.sumber
super.onSaveInstanceState()
.Cukup panggil super.onPostResume () sebelum menampilkan fragmen Anda atau pindahkan kode Anda di metode onPostResume () setelah memanggil super.onPostResume (). Ini menyelesaikan masalah!
sumber
Ini juga dapat terjadi ketika memanggil
dismiss()
fragmen dialog setelah layar dikunci \ blanked dan keadaan instance dialog + Aktivitas telah disimpan. Untuk menyiasati panggilan ini:Secara harfiah setiap kali saya menolak dialog saya tidak peduli tentang keadaan itu lagi, jadi ini tidak masalah untuk dilakukan - Anda sebenarnya tidak kehilangan status apa pun.
sumber
Solusi singkat dan bekerja:
Ikuti Langkah Sederhana:
Langkah 1 : Ganti status onSaveInstanceState di masing-masing fragmen. Dan hapus metode super dari itu.
Langkah 2 : Gunakan CommitAllowingStateLoss (); alih-alih komit (); sementara operasi fragmen.
sumber
Saya pikir keadaan Siklus Hidup dapat membantu mencegah kerusakan seperti itu dimulai dari dukungan Android lib v26.1.0 Anda dapat melakukan pemeriksaan berikut:
atau Anda dapat mencoba:
informasi lebih lanjut di sini https://developer.android.com/reference/android/support/v4/app/Fragment.html#isStateSaved ()
sumber
ini bekerja untuk saya ... menemukan ini sendiri ... semoga membantu Anda!
1) JANGAN memiliki global "statis" FragmentManager / FragmentTransaction.
2) onCreate, SELALU menginisialisasi FragmentManager lagi!
contoh di bawah ini: -
sumber
Saya selalu mendapatkan ini ketika saya mencoba untuk menunjukkan fragmen dalam metode onActivityForResult (), jadi masalahnya adalah berikutnya:
Apa yang saya buat selanjutnya:
sumber
Saya memecahkan masalah dengan perubahan konfigurasi. Caranya adalah bahwa menurut siklus hidup aktivitas android, ketika Anda secara eksplisit disebut niat (niat kamera, atau yang lainnya); aktivitas dijeda dan onsavedInstance dipanggil dalam kasus itu. Saat memutar perangkat ke posisi lain selain dari yang selama aktivitas itu aktif; melakukan operasi fragmen seperti fragmen komit menyebabkan pengecualian keadaan ilegal. Ada banyak keluhan tentang hal itu. Ini adalah sesuatu tentang manajemen siklus aktivitas Android dan pemanggilan metode yang tepat. Untuk mengatasinya saya lakukan ini: 1-Override metode onsavedInstance dari aktivitas Anda, dan tentukan orientasi layar saat ini (potret atau lanskap) kemudian atur orientasi layar Anda ke sana sebelum aktivitas Anda dijeda. dengan cara itu aktivitas Anda mengunci rotasi layar untuk aktivitas Anda seandainya telah diputar oleh yang lain. 2-kemudian, ganti metode aktivitas onresume, dan atur mode orientasi Anda sekarang ke sensor sehingga setelah metode yang dipanggil dipanggil akan memanggil sekali lagi konfigurasi untuk menangani rotasi dengan benar.
Anda dapat menyalin / menempelkan kode ini ke aktivitas Anda untuk menghadapinya:
sumber
Saya memiliki masalah yang sama, mendapatkan IllegalStateException, tetapi mengganti semua panggilan saya untuk melakukan () dengan commitAllowingStateLoss () tidak membantu.
Pelakunya adalah panggilan ke DialogFragment.show ().
Saya mengelilinginya
dan itu berhasil. OK, saya tidak bisa menampilkan dialog, tetapi dalam hal ini baik-baik saja.
Itu adalah satu-satunya tempat di aplikasi saya di mana saya pertama kali memanggil FragmentManager.beginTransaction () tetapi tidak pernah disebut commit () jadi saya tidak menemukannya ketika saya mencari "commit ()".
Lucunya, pengguna tidak pernah meninggalkan aplikasi. Sebaliknya si pembunuh adalah iklan pengantara AdMob yang muncul.
sumber
Solusi saya untuk masalah itu adalah
Dalam metode tambahkan fragmen:
Mungkin buruk, tetapi tidak dapat menemukan yang lebih baik.
sumber
Saya mendapatkan masalah ini. Namun saya pikir masalah ini tidak terkait dengan commit dan commitAllowStateLoss.
Tumpukan jejak jejak dan pesan pengecualian berikut adalah tentang commit ().
Tetapi pengecualian ini disebabkan oleh onBackPressed ()
Mereka semua disebabkan oleh checkStateLoss ()
mStateSaved akan benar setelah onSaveInstanceState.
Masalah ini jarang terjadi. Saya belum pernah mengalami masalah ini. Saya tidak dapat mengulangi masalah ini.
Saya menemukan masalah 25517
Itu mungkin terjadi dalam keadaan berikut
Tombol kembali dipanggil setelah onSaveInstanceState, tetapi sebelum aktivitas baru dimulai.
gunakan onStop () dalam kode
Saya tidak yakin apa akar masalahnya. Jadi saya menggunakan cara yang jelek.
sumber
Saya punya masalah yang sama di Aplikasi saya. Saya telah memecahkan masalah ini dengan memanggil
super.onBackPressed();
kelas sebelumnya dan memanggilcommitAllowingStateLoss()
kelas saat ini dengan fragmen itu.sumber
commitAllowingStateLoss()
alih-alihcommit()
onSaveInstance akan dipanggil jika pengguna memutar layar sehingga dapat memuat sumber daya yang terkait dengan orientasi baru.
Ada kemungkinan bahwa pengguna ini memutar layar diikuti dengan menekan tombol kembali (karena itu juga mungkin bahwa pengguna ini meraba-raba ponsel mereka saat menggunakan aplikasi Anda)
sumber
Baca http://chris-alexander.co.uk/on-engineering/dev/android-fragments-within-fragments/
artikel. memeriksa fragment.isResumed () membantu saya dalam onDestroyView tanpa menggunakan metode onSaveInstanceState.
sumber
Masalah yang sama dari saya dan setelah sehari analisis semua artikel, blog dan stackoverflow saya telah menemukan solusi sederhana. Jangan gunakan saveInstanceState sama sekali, ini adalah kondisi dengan satu baris kode. Pada kode fragmen:
sumber
Ini terjadi setiap kali Anda mencoba memuat fragmen tetapi aktivitas telah mengubah statusnya menjadi onPause (). Ini terjadi misalnya ketika Anda mencoba mengambil data dan memuatnya ke aktivitas tetapi pada saat pengguna telah mengklik beberapa tombol dan telah dipindahkan ke aktivitas berikutnya.
Anda dapat menyelesaikan ini dengan dua cara
Anda dapat menggunakan transaction.commitAllowingStateLoss () alih-alih transaction.commit () untuk memuat fragmen tetapi Anda akhirnya bisa kehilangan operasi komit yang dilakukan.
atau
Pastikan aktivitas sedang dalam resume dan tidak akan berhenti saat memuat fragmen. Buat boolean dan periksa apakah aktivitas tidak akan menjadi status onPause ().
lalu sambil memuat fragmen, periksa apakah aktivitas ada dan muat hanya saat aktivitas dilatar depan.
sumber
Terima kasih @gunar, tapi saya rasa ada cara yang lebih baik.
Menurut dokumen:
Jadi gunakan
commitNow
untuk mengganti:sumber
Nah, setelah mencoba semua solusi di atas tidak berhasil (karena pada dasarnya saya tidak punya transaksi).
Dalam kasus saya, saya menggunakan AlertDialogs dan ProgressDialog sebagai fragmen yang, kadang-kadang, pada rotasi, ketika meminta FragmentManager, kesalahan muncul.
Saya menemukan pemecahan masalah menggabungkan beberapa posting serupa:
Ini adalah solusi 3 langkah, semua dilakukan pada FragmentActivity Anda (dalam hal ini, yang disebut GenericActivity):
sumber
Ketika saya menggunakan startactivity dalam satu fragmen, saya akan mendapatkan pengecualian ini;
Ketika saya mengubah untuk menggunakan startactivityforresult, pengecualian hilang :)
Jadi cara mudah untuk memperbaikinya adalah menggunakan api startActivityForResult :)
sumber
Saya mendapatkan pengecualian ini ketika saya menekan tombol kembali untuk membatalkan pemilih pemilih pada aktivitas fragmen peta saya. Saya menyelesaikan ini dengan mengganti kode onResume () (di mana saya menginisialisasi fragmen dan melakukan transaksi) ke onStart () dan aplikasi bekerja dengan baik sekarang. Semoga ini bisa membantu.
sumber
Ini diperbaiki di Android 4.2 dan juga di sumber perpustakaan dukungan. [*]
Untuk detail penyebabnya (dan penyelesaiannya) lihat laporan bug Google: http://code.google.com/p/android/issues/detail?id=19917
Jika Anda menggunakan perpustakaan dukungan maka Anda tidak perlu khawatir tentang bug ini (lama) [*]. Namun, jika Anda menggunakan API secara langsung (mis. Tidak menggunakan FragmentManager perpustakaan dukungan) dan menargetkan API di bawah Android 4.2 maka Anda harus mencoba salah satu solusi.
[*] Pada saat penulisan, Android SDK Manager masih mendistribusikan versi lama yang menunjukkan bug ini.
Edit Saya akan menambahkan beberapa klarifikasi di sini karena saya jelas-jelas bingung siapa pun yang memilih jawaban ini.
Ada beberapa keadaan yang berbeda (namun terkait) yang dapat menyebabkan pengecualian ini dilemparkan . Jawaban saya di atas mengacu pada contoh spesifik yang dibahas dalam pertanyaan yaitu bug di Android yang kemudian diperbaiki. Jika Anda mendapatkan pengecualian ini karena alasan lain, itu karena Anda menambahkan / menghapus fragmen ketika seharusnya tidak (setelah status fragmen disimpan). Jika Anda berada dalam situasi seperti itu, maka mungkin " Nested Fragments - IllegalStateException" Tidak dapat melakukan tindakan ini setelah onSaveInstanceState " " dapat bermanfaat bagi Anda.
sumber
Setelah meneliti sedikit, solusi untuk masalah ini adalah dengan melakukan fragmen Anda di onresume.
Sumber: https://wenchaojames.wordpress.com/2013/01/12/illegalstateexception-from-onactivityresult/
sumber
Kasus penggunaan saya: Saya telah menggunakan pendengar secara terpisah untuk memberi tahu aktivitas bahwa sesuatu telah terjadi. Saya melakukan fragmen baru pada metode panggilan balik. Ini bekerja dengan sangat baik pada kali pertama. Tetapi pada perubahan orientasi aktivitas diciptakan kembali dengan keadaan instance disimpan. Dalam hal itu fragmen tidak dibuat lagi menyiratkan bahwa fragmen tersebut memiliki pendengar yang sudah lama dihancurkan aktivitasnya. Bagaimana pun metode panggilan balik akan terpicu saat beraksi. Pergi ke aktivitas yang hancur yang menyebabkan masalah. Solusinya adalah mengatur ulang pendengar secara terpisah dengan aktivitas langsung saat ini. Ini menyelesaikan masalah.
sumber
Apa yang saya temukan adalah bahwa jika aplikasi lain adalah tipe dialog dan memungkinkan sentuhan untuk dikirim ke aplikasi latar belakang maka hampir semua aplikasi latar belakang akan crash dengan kesalahan ini. Saya pikir kita perlu memeriksa setiap kali transaksi dilakukan jika instance disimpan atau dikembalikan.
sumber
Dalam kasus saya, dengan pengecualian kesalahan yang sama, saya meletakkan "onBackPressed ()" di runnable (Anda dapat menggunakan salah satu dari tampilan Anda):
Saya tidak mengerti mengapa, tetapi itu berhasil!
sumber
Anda mungkin memanggil fragmentManager.popBackStackImmediate (); ketika aktivitas dijeda. Aktivitas belum selesai tetapi dijeda dan tidak di latar depan. Anda perlu memeriksa apakah aktivitas dijeda atau tidak sebelum popBackStackImmediate ().
sumber
Saya perhatikan sesuatu yang sangat menarik. Di aplikasi saya ada opsi untuk membuka galeri ponsel dan perangkat menanyakan aplikasi apa yang harus digunakan, di sana saya mengklik area abu-abu menjauh dari dialog dan melihat masalah ini. Saya perhatikan bagaimana aktivitas saya berjalan dari onPause, onSaveInstanceState kembali ke onResume, itu tidak terjadi untuk mengunjungi onCreateView. Saya melakukan transaksi di onResume. Jadi apa yang akhirnya saya lakukan adalah mengatur bendera yang dinegasikan pada jeda, tetapi menjadi benar onCreateView. jika flag benar padaResume maka lakukan onCommit, jika tidak, commitAllowingStateLoss. Saya bisa terus dan menghabiskan begitu banyak waktu tetapi saya ingin memeriksa siklus hidupnya. Saya memiliki perangkat yang merupakan sdkversion 23, dan saya tidak mendapatkan masalah ini, tetapi saya memiliki satu lagi yang 21, dan di sana saya melihatnya.
sumber
Anda dapat menggunakan FragmentActivity.onStart sebelum popBackStackImmediate
seperti ini:
http://jorryliu.blogspot.com/2014/09/illegalstateexception-can-not-perform.html
sumber