Beberapa pengguna melaporkan, jika mereka menggunakan tindakan cepat di bilah notifikasi, mereka mendapatkan penutupan paksa.
Saya menunjukkan tindakan cepat dalam notifikasi yang memanggil kelas "TestDialog" . Di kelas TestDialog setelah menekan tombol "snooze", saya akan menampilkan SnoozeDialog.
private View.OnClickListener btnSnoozeOnClick() {
return new View.OnClickListener() {
public void onClick(View v) {
showSnoozeDialog();
}
};
}
private void showSnoozeDialog() {
FragmentManager fm = getSupportFragmentManager();
SnoozeDialog snoozeDialog = new SnoozeDialog();
snoozeDialog.show(fm, "snooze_dialog");
}
Kesalahannya adalah *IllegalStateException: Can not perform this action after onSaveInstanceState*.
Baris kode tempat IllegarStateException diaktifkan adalah:
snoozeDialog.show(fm, "snooze_dialog");
Kelas memperluas "FragmentActivity" dan kelas "SnoozeDialog" memperluas "DialogFragment".
Berikut adalah jejak tumpukan lengkap dari kesalahan tersebut:
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1327)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1338)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574)
at android.support.v4.app.DialogFragment.show(DialogFragment.java:127)
at com.test.testing.TestDialog.f(TestDialog.java:538)
at com.test.testing.TestDialog.e(TestDialog.java:524)
at com.test.testing.TestDialog.d(TestDialog.java:519)
at com.test.testing.g.onClick(TestDialog.java:648)
at android.view.View.performClick(View.java:3620)
at android.view.View$PerformClick.run(View.java:14292)
at android.os.Handler.handleCallback(Handler.java:605)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4507)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
at dalvik.system.NativeStart.main(Native Method)
Saya tidak dapat mereproduksi kesalahan ini, tetapi saya mendapatkan banyak laporan kesalahan.
Adakah yang bisa membantu bagaimana cara memperbaiki kesalahan ini?
Jawaban:
Ini adalah masalah umum . Kami memecahkan masalah ini dengan mengganti show () dan menangani pengecualian di kelas diperpanjang DialogFragment
Perhatikan bahwa menerapkan metode ini tidak akan mengubah bidang internal DialogFragment.class:
Ini dapat menyebabkan hasil yang tidak terduga dalam beberapa kasus. Lebih baik gunakan commitAllowingStateLoss () daripada commit ()
sumber
Itu berarti Anda
commit()
(show()
dalam kasus DialogFragment) setelahnyaonSaveInstanceState()
.Android akan menyimpan status fragmen Anda di
onSaveInstanceState()
. Jadi, jika Andacommit()
fragmen setelahonSaveInstanceState()
status fragmen akan hilang.Akibatnya, jika Aktivitas dimatikan dan dibuat ulang nanti, fragmen tidak akan menambah aktivitas yang merupakan pengalaman pengguna yang buruk. Itulah mengapa Android tidak mengizinkan kerugian negara dengan cara apa pun.
Solusi mudahnya adalah memeriksa apakah status sudah disimpan.
Catatan: onResumeFragments () akan dipanggil saat fragmen dilanjutkan.
sumber
ref: tautan
sumber
Setelah beberapa hari saya ingin berbagi solusi saya bagaimana saya sudah tetap itu, untuk menunjukkan DialogFragment Anda harus menimpa
show()
metode itu dan memanggilcommitAllowingStateLoss()
padaTransaction
objek. Berikut adalah contoh di Kotlin:sumber
DialogFragment
Anda bisa mengubah ini menjadi fungsi ekstensi Kotlin dengan tanda tangan berikut:fun DialogFragment.showAllowingStateLoss(fragmentManager: FragmentManager, tag: String)
. Selain itu, coba-tangkap tidak diperlukan karena Anda memanggilcommitAllowingStateLoss()
metode dan bukancommit()
metode.Jika dialog tidak terlalu penting (tidak apa-apa untuk tidak menampilkannya saat aplikasi ditutup / tidak lagi terlihat), gunakan:
Dan buka dialog Anda (fragmen) hanya saat kami menjalankan:
EDIT, SOLUSI YANG LEBIH BAIK MUNGKIN:
Di mana onSaveInstanceState dipanggil dalam siklus hidup tidak dapat diprediksi, saya pikir solusi yang lebih baik adalah memeriksa isSavedInstanceStateDone () seperti ini:
sumber
Saya telah mengalami masalah ini selama bertahun-tahun.
Internet dipenuhi dengan puluhan (ratusan? Ribuan?) Diskusi tentang hal ini, dan kebingungan serta disinformasi di dalamnya tampaknya banyak sekali.
Untuk memperburuk situasi, dan dalam semangat xkcd "14 standar" komik, saya melempar jawaban saya ke ring.
The
cancelPendingInputEvents()
,commitAllowingStateLoss()
,catch (IllegalStateException e)
, dan solusi sejenis semua tampak mengerikan.Semoga berikut ini dengan mudah menunjukkan cara mereproduksi dan memperbaiki masalah:
sumber
coba gunakan FragmentTransaction sebagai ganti FragmentManager. Saya pikir kode di bawah ini akan menyelesaikan masalah Anda. Jika tidak, tolong beritahu saya.
EDIT:
Transaksi Fragmen
Silakan periksa tautan ini. Saya pikir itu akan menyelesaikan pertanyaan Anda.
sumber
Menggunakan cakupan siklus hidup baru Activity-KTX sesederhana contoh kode berikut:
Metode ini bisa langsung dipanggil setelah onStop () dan akan berhasil menampilkan dialog setelah onResume () dipanggil setelah kembali.
sumber
Banyak tampilan memposting peristiwa tingkat tinggi seperti penangan klik ke antrean acara untuk menjalankan ditangguhkan. Jadi masalahnya adalah bahwa "onSaveInstanceState" telah dipanggil untuk Aktivitas tetapi antrian acara berisi "peristiwa klik" yang ditangguhkan. Karenanya saat acara ini dikirim ke pawang Anda
dan kode Anda
show
menjalankan IllegalStateException.Solusi paling sederhana adalah membersihkan antrian acara, di
onSaveInstanceState
sumber
activity
danfragment
).Jadikan objek fragmen dialog Anda global dan panggil rejectAllowingStateLoss () dalam metode onPause ()
Jangan lupa untuk menetapkan nilai dalam fragmen dan memanggil show () pada klik tombol atau di mana pun.
sumber
Meskipun tidak disebutkan secara resmi di mana pun tetapi saya menghadapi masalah ini beberapa kali. Menurut pengalaman saya, ada sesuatu yang salah dalam library kompatibilitas yang mendukung fragmen pada platform lama yang menyebabkan masalah ini. Anda menggunakan uji ini dengan menggunakan API pengelola fragmen normal. Jika tidak ada yang berhasil, Anda dapat menggunakan dialog normal sebagai ganti fragmen dialog.
sumber
Gunakan metode showAllowingStateLoss daripada show
Nikmati ;)
sumber
StatelessDialogFragment
dalam salah satu paket saya. Terima kasih bung, Saya akan mengujinya dalam produksi segera.gunakan kode ini
dari pada
sumber
Saya telah menemukan solusi elegan untuk masalah ini dengan menggunakan refleksi. Masalah dari semua solusi di atas adalah bidang mDismissed dan mShownByMe tidak mengubah statusnya .
Cukup ganti metode "tampilkan" dalam fragmen dialog lembar bawah kustom Anda sendiri seperti contoh di bawah (Kotlin)
sumber
Implementasi berikut dapat digunakan untuk memecahkan masalah melakukan perubahan status dengan aman selama
Activity
siklus hidup, khususnya untuk menampilkan dialog: jika status instans telah disimpan (misalnya karena perubahan konfigurasi), ia akan menundanya hingga status dilanjutkan telah dilakukan.Kemudian gunakan kelas seperti ini:
Anda dapat dengan aman menampilkan dialog tanpa mengkhawatirkan status aplikasi:
dan kemudian panggil
TestDialog.show(this)
dari dalam AndaXAppCompatActivity
.Jika Anda ingin membuat kelas dialog yang lebih umum dengan parameter, Anda dapat menyimpannya di a
Bundle
dengan argumen dishow()
metode dan mengambilnya dengangetArguments()
inonCreateDialog()
.Keseluruhan pendekatan mungkin tampak sedikit rumit, tetapi setelah Anda membuat dua kelas dasar untuk aktivitas dan dialog, ini cukup mudah digunakan dan bekerja dengan sempurna. Ini dapat digunakan untuk
Fragment
operasi berbasis lain yang dapat dipengaruhi oleh masalah yang sama.sumber
Kesalahan ini tampaknya terjadi karena peristiwa masukan (seperti peristiwa key down atau onclick) dikirim setelah
onSaveInstanceState
dipanggil.Solusinya adalah menimpa
onSaveInstanceState
Aktivitas Anda dan membatalkan acara yang menunggu keputusan.sumber