Apakah ini cara yang tepat untuk membersihkan tumpukan back Fragment ketika meninggalkan tumpukan bersarang mendalam?

130

Saya menggunakan pustaka Kompatibilitas Android untuk mengimplementasikan fragmen dan telah memperluas sampel tata letak sehingga fragmen berisi tombol yang melepaskan fragmen lain.

Di panel pilihan di sebelah kiri saya memiliki 5 item yang dipilih - A B C D E.

Setiap memuat fragmen (melalui FragmentTransaction:replace) di panel detail -a b c d e

Sekarang saya telah memperluas fragmen eberisi tombol yang memuat fragmen lain e1juga di panel rincian. Saya telah melakukan ini pada emetode onClick fragmen sebagai berikut:

FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ft.replace(R.id.details_frag, newFrag);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();

Jika saya membuat pilihan berikut:

E - e - e1 - D - E

Kemudian fragmen eada di panel detail. Ini baik dan apa yang saya inginkan. Namun, jika saya menekan backtombol pada saat ini tidak ada artinya. Saya harus mengklik dua kali karena e1masih di tumpukan. Selanjutnya setelah mengklik sekitar saya mendapat pengecualian pointer nol di onCreateView:

Untuk 'memecahkan' masalah ini saya menambahkan yang berikut setiap kali A B C D Edipilih:

FragmentManager fm = getActivity().getSupportFragmentManager();
for(int i = 0; i < fm.getBackStackEntryCount(); ++i) {
    fm.popBackStack();
}

Hanya ingin tahu apakah ini solusi yang tepat atau apakah saya harus melakukan sesuatu yang berbeda?

PJL
sumber

Jawaban:

252

Ya ada beberapa cara untuk melakukan ini tergantung pada perilaku yang dimaksud, tetapi tautan ini harus memberi Anda semua solusi terbaik dan tidak mengherankan dari Dianne Hackborn

http://groups.google.com/group/android-developers/browse_thread/thread/d2a5c203dad6ec42

Pada dasarnya Anda memiliki opsi berikut

  • Gunakan nama untuk kondisi back stack awal Anda dan gunakan FragmentManager.popBackStack(String name, FragmentManager.POP_BACK_STACK_INCLUSIVE).
  • Gunakan FragmentManager.getBackStackEntryCount()/ getBackStackEntryAt().getId() untuk mengambil ID dari entri pertama di tumpukan belakang, dan FragmentManager.popBackStack(int id, FragmentManager.POP_BACK_STACK_INCLUSIVE).
  • FragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE) seharusnya pop seluruh tumpukan kembali ... Saya pikir dokumentasi untuk itu hanya salah. (Sebenarnya saya kira itu tidak mencakup kasus di mana Anda lewat POP_BACK_STACK_INCLUSIVE),
Joachim
sumber
Apa artinya ini? FragmentManager.getBackStackEntryCount () / getBackStackEntryAt (). GetId ()
dannyroa
4
2nd bekerja untuk saya. Apa artinya untuk menghapus seluruh tumpukan: getSupportFragmentManager (). PopBackStack (getSupportFragmentManager (). GetBackStackEntryAt (0) .getId (), FragmentManager.POP_BACK_STACK_INCLUSIVE);
NickL
@JorgeGarcia apakah mungkin setelah popbackstack kami baru saja menyelesaikan fragmen kami tanpa memulai ulang yang lebih lama.
duggu
Harap dicatat ada juga versi popBackStackImmediate () karena popBackStack () async, yang berarti proses pembersihan tidak terjadi pada saat Anda memanggil metode.
Genc
6
Klaim grup ini dilarang sebagai spam dan saya tidak dapat mengakses tautan :( adakah yang punya sumber daya di tempat lain?
EpicPandaForce
61

Solusi bersih lainnya jika Anda tidak ingin mem-pop semua entri stack ...

getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
getSupportFragmentManager().beginTransaction().replace(R.id.home_activity_container, fragmentInstance).addToBackStack(null).commit();

Ini akan membersihkan tumpukan lebih dulu dan kemudian memuat fragmen baru, jadi pada titik tertentu Anda hanya akan memiliki satu fragmen di tumpukan

Pawan Maheshwari
sumber
1
Hal ini sangat buruk: getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);sebelum ganti () karena memuat panggilan Fragment onCreateView(), onActivityCreated(), dll Memulihkan dan Destroing sebuah Fragmen langsung buruk. Fragmen dapat mendaftarkan penerima misalnya. Ini memengaruhi kinerja.
VasileM
@VileileM, dapatkah Anda menjelaskan secara detail? Dalam kasus apa itu buruk? Apakah karena perilaku asynhronous FragmentTransaction? Apakah hanya ada kinerja buruk tumpukan fragmen yang salah?
CoolMind
27

Berkat jawaban Joachim , saya menggunakan kode untuk menghapus semua entri tumpukan kembali akhirnya.

// In your FragmentActivity use getSupprotFragmentManager() to get the FragmentManager.

// Clear all back stack.
int backStackCount = getSupportFragmentManager().getBackStackEntryCount();
for (int i = 0; i < backStackCount; i++) {

    // Get the back stack fragment id.
    int backStackId = getSupportFragmentManager().getBackStackEntryAt(i).getId();

    getSupportFragmentManager().popBackStack(backStackId, 
        FragmentManager.POP_BACK_STACK_INCLUSIVE);

} /* end of for */
Jay Parker
sumber
18
Mengapa menggunakan loop di sini? Bagi saya FragmentManager.popBackStack (null, FragmentManager.POP_BACK_STACK_INCLUSIVE) menghapus semua entri tumpukan belakang ...
Marek
3
@ Marsek, karena kadang-kadang tidak semua fragmen harus dihapus, loop cocok untuk ini.
CoolMind
1
@ CoolMind, itu masih tidak masuk akal bagi saya. popBackStack(backStackId, INCLUSIVE)akan memunculkan semua fragmen (status) kembali ke backStackId, jadi setelah Anda mem-pop up terendah iyang akan Anda pop, semua yang lebih tinggi akan muncul pada waktu yang sama. Jadi apa gunanya loop?
LarsH
@ LarsH, kamu benar. Lihat stackoverflow.com/a/59158254/2914140 . Untuk memunculkan fragmen lain ke tag yang diperlukan, pertama-tama kita harus menambahkan fragmen dengan addToBackStack ( tag ).
CoolMind
7

Saya telah banyak meneliti untuk membersihkan Backstack, dan akhirnya melihat Transaction BackStack dan manajemennya . Inilah solusi yang paling cocok untuk saya.

 // CLEAR BACK STACK.
    private void clearBackStack() {
        final FragmentManager fragmentManager = getSupportFragmentManager();
        while (fragmentManager.getBackStackEntryCount() != 0) {
            fragmentManager.popBackStackImmediate();
        }
    }

Metode di atas loop semua transaksi di backstack dan menghapusnya segera satu per satu.

Catatan: kode di atas kadang tidak berfungsi dan saya menghadapi ANR karena kode ini, jadi tolong jangan coba ini.

Perbarui metode di bawah ini menghapus semua fregment dari "nama" itu dari backstack.

FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.popBackStack("name",FragmentManager.POP_BACK_STACK_INCLUSIVE);
  • name Jika bukan nol, ini adalah nama dari kondisi sebelumnya yang dicari; jika ditemukan, semua status hingga status itu akan muncul. Itu
  • Bendera POP_BACK_STACK_INCLUSIVE dapat digunakan untuk mengontrol apakah keadaan yang disebutkan itu muncul. Jika nol, hanya kondisi teratas yang muncul.
Lokesh
sumber
Saya tidak mengerti mengapa Anda menghapusnya satu per satu. Apakah ada alasan mengapa Anda memilih untuk solusi ini daripada solusi lainnya? Apakah ada alasan untuk menghapusnya satu per satu alih-alih sekaligus?
miva2
Tidak ada metode untuk menghapus backstack pada satu waktu, lihat developer.android.com/reference/android/app/…
Lokesh
3

Saya menggunakan kode yang sama dengan yang menggunakan loop sementara tapi saya menyebut jumlah entri di setiap loop ... jadi saya kira itu agak lambat

FragmentManager manager = getFragmentManager();
while (manager.getBackStackEntryCount() > 0){
        manager.popBackStackImmediate();
    }
Jorge Lozano
sumber
0

Seperti yang ditulis dalam Bagaimana cara mem-fragmen backstack dan oleh LarsH di sini, kita dapat mem -pop beberapa fragmen dari atas ke bawah ke tag khusus ( bersama dengan fragmen yang ditandai ) menggunakan metode ini:

fragmentManager?.popBackStack ("frag", FragmentManager.POP_BACK_STACK_INCLUSIVE);

Ganti "frag" dengan tag fragmen Anda. Ingat bahwa pertama-tama kita harus menambahkan fragmen ke backstack dengan:

fragmentTransaction.addToBackStack("frag")

Jika kami menambahkan fragmen addToBackStack(null), kami tidak akan memecah fragmen dengan cara itu.

CoolMind
sumber
-4
    // pop back stack all the way
    final FragmentManager fm = getSherlockActivity().getSupportFragmentManager();
    int entryCount = fm.getBackStackEntryCount(); 
    while (entryCount-- > 0) {
        fm.popBackStack();
    }
farid_z
sumber