Bersihkan tumpukan menggunakan fragmen

244

Saya porting aplikasi Android saya ke honeycomb dan saya melakukan refactor besar untuk menggunakan fragmen. Dalam versi saya sebelumnya, ketika saya menekan tombol Home saya biasa melakukan ACTIVITY_CLEAR_TOPuntuk mengatur ulang tumpukan kembali.

Sekarang aplikasi saya hanya satu Kegiatan dengan beberapa fragmen, jadi ketika saya menekan tombol Beranda saya hanya mengganti salah satu fragmen di dalamnya. Bagaimana saya bisa membersihkan saya tumpukan kembali tanpa harus menggunakan startActivitydengan ACTIVITY_CLEAR_TOPbendera?

biquillo
sumber
Hindari menggunakan tumpukan belakang! itu tidak benar-benar membantu dengan efisiensi keseluruhan! gunakan ganti polos () atau hapus / tambah lebih baik setiap kali Anda ingin menavigasi! Periksa posting saya di stackoverflow.com/questions/5802141/…
stack_ved

Jawaban:

430

Saya memposting sesuatu yang serupa di sini

Dari jawaban Joachim, dari Dianne Hackborn:

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

Saya akhirnya hanya menggunakan:

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

Tetapi bisa sama-sama menggunakan sesuatu seperti:

((AppCompatActivity)getContext()).getSupportFragmentManager().popBackStack(String name, FragmentManager.POP_BACK_STACK_INCLUSIVE)

Yang akan muncul semua negara hingga yang disebutkan. Anda kemudian dapat mengganti fragmen dengan apa yang Anda inginkan

PJL
sumber
8
Yah, itu sama dengan menekan tombol kembali satu kali atau lebih, sehingga itu mengubah fragmen yang saat ini terlihat. (Setidaknya ketika saya sudah mencobanya)
Peter Ajtai
7
Saya memiliki masalah yang sama dengan Peter. Saya ingin membersihkan semua fragmen daripada memutarnya melalui mereka yang memiliki banyak implikasi. Misalnya, Anda akan menekan acara siklus hidup yang tidak perlu Anda lakukan dengan mengeluarkan setiap fragmen dari tumpukan secara berurutan.
Brian Griffey
233
Untuk menuju ke atas cukup gunakan: fragmentManager.popBackStack (null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
Warpzit
53
Untuk apa nilainya, menggunakan fragmentManager. popBackStackImmediate (null, FragmentManager.POP_BACK_STACK_INCLUSIVE); bekerja lebih baik bagi saya karena mencegah animasi fragmen dari mengeksekusi
roarster
17
Ini TIDAK berfungsi dengan baik - itu akan memicu panggilan untuk memulai setiap fragmen di antara
James
165

Untuk membuat jawaban untuk komentar @ Warpzit dan membuatnya lebih mudah bagi orang lain untuk menemukannya.

Menggunakan:

fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
Morten Holmgaard
sumber
14
Saya percaya muncul semua fragmen dari backstack dengan cara ini telah rusak di perpustakaan v7-appCompat terbaru saat menggunakan AppCompatActivity. Setelah memperbarui aplikasi saya ke pustaka v7-appCompat terbaru (21.0.0) dan memperluas AppCompatActivity baru, muncul fragmen dengan cara di atas meninggalkan beberapa fragmen dalam catatan backstack dari FragmentManager. Saya menyarankan agar tidak menggunakan ini.
dell116
Dapat menggunakan popBackStackImmediate.
Kannan_SJD
38

Dengan segala hormat kepada semua pihak yang terlibat; Saya sangat terkejut melihat berapa banyak dari Anda yang bisa membersihkan seluruh tumpukan back fragmen dengan sederhana

fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);

Menurut dokumentasi Android (mengenai nameargumen - "null" dalam proposal kerja yang diklaim).

Jika nol, hanya kondisi teratas yang muncul

Sekarang, saya menyadari bahwa saya kurang pengetahuan tentang implementasi khusus Anda (seperti berapa banyak entri yang Anda miliki di tumpukan belakang pada titik waktu tertentu), tetapi saya berani bertaruh semua uang saya pada jawaban yang diterima ketika mengharapkan yang terdefinisi dengan baik perilaku pada berbagai perangkat dan vendor:

(untuk referensi, sesuatu bersama dengan ini)

FragmentManager fm = getFragmentManager(); // or 'getSupportFragmentManager();'
int count = fm.getBackStackEntryCount();
for(int i = 0; i < count; ++i) {    
    fm.popBackStack();
}
dbm
sumber
4
bagi saya itu bukan karena setiap pop membawa Anda secara internal ke onCreateView setiap fragmen. Di mana saya akan menerima NPE pada beberapa sumber daya. Tetapi menggunakan fm.popBackStack (null, FragmentManager.POP_BACK_STACK_INCLUSIVE); hanya membunuh semua backstack.
sud007
1
Adakah wawasan tentang cara melewatkan panggilan onCreateView saat muncul menggunakan loop?
Ayush Goyal
Mengosongkan fragmen paling atas (null) akan menghapus semua fragmen yang datang setelah itu di tumpukan belakang.
2b77bee6-5445-4c77-b1eb-4df3e5
18

Bekerja untuk saya dan cara mudah tanpa menggunakan loop:

 FragmentManager fragmentManager = getSupportFragmentManager();
 //this will clear the back stack and displays no animation on the screen
 fragmentManager.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
Md Mohsin
sumber
17

Jawaban yang diterima tidak cukup bagi saya. Saya harus menggunakan:

FragmentManager fm = getSupportFragmentManager();
int count = fm.getBackStackEntryCount();
for(int i = 0; i < count; ++i) {
    fm.popBackStackImmediate();
}
belphegor
sumber
2
Ini ditunjukkan dalam jawaban yang berbeda, tetapi hanya untuk memastikannya dicatat: Jika Anda mem-pop seluruh tumpukan dalam satu lingkaran seperti ini, Anda akan memicu metode siklus hidup untuk setiap Fragmen di antara awal dan akhir tumpukan . Ada peluang bagus bahwa implementasi ini akan memiliki konsekuensi yang tidak diinginkan, dalam sebagian besar kasus penggunaan. Penting juga menunjukkan bahwa popBackStackImmediate()melakukan transaksi secara serempak, yang, secara umum, keliru.
Damien Diehl
16

Bersihkan backstack tanpa loop

String name = getSupportFragmentManager().getBackStackEntryAt(0).getName();
getSupportFragmentManager().popBackStack(name, FragmentManager.POP_BACK_STACK_INCLUSIVE);

Di mana nama adalah parameter addToBackStack ()

getSupportFragmentManager().beginTransaction().
                .replace(R.id.container, fragments.get(titleCode))
                .addToBackStack(name)
georgehardcore
sumber
bahkan jika Anda mengganti tumpukan .fragment akan hidup tetapi tidak terlihat
Asthme
8

Saya hanya ingin menambahkan: -

Muncul keluar dari backstack menggunakan yang berikut

fragmentManager.popBackStack ()

hanya tentang menghilangkan fragmen dari transaksi, tidak ada cara untuk menghapus fragmen dari layar. Jadi idealnya, itu mungkin tidak terlihat oleh Anda tetapi mungkin ada dua atau tiga fragmen ditumpuk satu sama lain, dan pada tombol kembali tekan UI mungkin terlihat berantakan, ditumpuk.

Hanya mengambil contoh sederhana: -

Misalkan Anda memiliki fragmentA yang memuat Fragmnet B menggunakan fragmentmanager.replace () dan kemudian kami menambahkanToBackStack, untuk menyimpan transaksi ini. Jadi arusnya adalah: -

LANGKAH 1 -> FragmentA-> FragmentB (kami pindah ke FragmentB, tetapi Fragment A ada di latar belakang, tidak terlihat).

Sekarang Anda melakukan beberapa pekerjaan di fragmentB dan tekan tombol Simpan - yang setelah menyimpan harus kembali ke fragmentA.

LANGKAH 2 -> Saat menyimpan FragmentB, kita kembali ke FragmentA.

LANGKAH 3 -> Jadi kesalahan umum adalah ... dalam Fragmen B, kami akan melakukan fragmen Manager.replace () fragmentB dengan fragmentA.

Tetapi apa yang sebenarnya terjadi, kami memuat Fragment A lagi, menggantikan FragmentB. Jadi sekarang ada dua FragmentA (satu dari LANGKAH-1, dan satu dari LANGKAH-3 ini).

Dua contoh FragmentsA ditumpuk satu sama lain, yang mungkin tidak terlihat, tetapi ada di sana.

Jadi, bahkan jika kita menghapus backstack dengan metode di atas, transaksi itu dihapus tetapi bukan fragmen yang sebenarnya. Jadi idealnya dalam kasus tertentu, dengan menekan tombol simpan Anda hanya perlu kembali ke fragmentA dengan hanya melakukan fm.popBackStack () atau fm.popBackImmediate () .

Jadi perbaiki Step3-> fm.popBackStack () kembali ke fragmentA, yang sudah ada dalam memori.

Torehan
sumber
3

Membaca dokumentasi dan mempelajari apa id fragmen itu, tampaknya hanya menjadi indeks tumpukan, jadi ini berfungsi:

fragmentManager.popBackStackImmediate(0, FragmentManager.POP_BACK_STACK_INCLUSIVE);

Nol ( 0) adalah bagian bawah tumpukan, jadi muncul hingga itu termasuk membersihkan tumpukan.

CAVEAT: Meskipun cara di atas berfungsi dalam program saya, saya sedikit ragu karena dokumentasi FragmentManager tidak pernah benar-benar menyatakan bahwa id adalah indeks tumpukan. Masuk akal bahwa itu akan terjadi, dan semua log debug saya menyatakan hal itu, tetapi mungkin dalam beberapa keadaan khusus tidak? Adakah yang bisa mengkonfirmasi ini dengan satu atau lain cara? Jika ya, maka solusi di atas adalah yang terbaik. Jika tidak, ini adalah alternatifnya:

while(fragmentManager.getBackStackEntryCount() > 0) { fragmentManager.popBackStackImmediate(); }
trans
sumber
1
Bagaimana kalau menggunakan fragmentManager..getBackStackEntryAt(0).getId()bukannya 0? Ini harus bekerja bahkan jika id entri backstack pada titik tertentu berbeda dari indeks tumpukan.
ChristophK
3

Cukup gunakan metode ini dan berikan tag Konteks & Fragmen ke atas yang kita perlukan untuk menghapus fragmen backstake.

Pemakaian

clearFragmentByTag(context, FragmentName.class.getName());



public static void clearFragmentByTag(Context context, String tag) {
    try {
        FragmentManager fm = ((AppCompatActivity) context).getSupportFragmentManager();

        for (int i = fm.getBackStackEntryCount() - 1; i >= 0; i--) {
            String backEntry = fm.getBackStackEntryAt(i).getName();
            if (backEntry.equals(tag)) {
                break;
            } else {
                 fm.popBackStack();
            }
        }
    } catch (Exception e) {
        System.out.print("!====Popbackstack error : " + e);
        e.printStackTrace();
    }
}
Arhat Baid
sumber
2

Hai ~ Saya menemukan solusi yang jauh lebih baik, dari: https://gist.github.com/ikew0ng/8297033

    /**
 * Remove all entries from the backStack of this fragmentManager.
 *
 * @param fragmentManager the fragmentManager to clear.
 */
private void clearBackStack(FragmentManager fragmentManager) {
    if (fragmentManager.getBackStackEntryCount() > 0) {
        FragmentManager.BackStackEntry entry = fragmentManager.getBackStackEntryAt(0);
        fragmentManager.popBackStack(entry.getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
    }
}
Chenxi
sumber
2
Harap perluas jawaban Anda dengan alasan solusi ini lebih baik.
Simon.SA
Ini menggunakan mekanisme yang disediakan SDK itu sendiri, dan tidak akan menyebabkan beberapa masalah npe.
Chenxi
1

Saya dapat ini dengan cara ini:

public void showHome() {
    getHandler().post(new Runnable() {
        @Override
        public void run() {
            final FragmentManager fm = getSupportFragmentManager();
            while (fm.getBackStackEntryCount() > 0) {
                fm.popBackStackImmediate();
            }
        }
    });
}
saulobrito
sumber
1

Ini bekerja untuk saya, coba yang ini:

public void clearFragmentBackStack() {
        FragmentManager fm = getSupportFragmentManager();
        for (int i = 0; i < fm.getBackStackEntryCount() - 1; i++) {
            fm.popBackStack();
        }
    }
Alok Singh
sumber
0
    private void clearBackStack(){
        SupportFragmentManaer fm = getSupportFragmentManager();
        fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
    }

Panggilan ke metode ini akan sangat rapi.

  1. Tidak diperlukan Loop.
  2. Jika Anda menggunakan animasi dalam fragmen, itu tidak akan menampilkan terlalu banyak animasi. Tetapi menggunakan loop akan.
Wajid Ali
sumber
0
private boolean removeFragFromBackStack() {
    try {
        FragmentManager manager = getSupportFragmentManager();
        List<Fragment> fragsList = manager.getFragments();
        if (fragsList.size() == 0) {
            return true;
        }
        manager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
        return true;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return false;
}
pengguna3509903
sumber
Terima kasih atas cuplikan kode ini, yang mungkin memberikan bantuan terbatas dan segera. Sebuah penjelasan yang tepat akan sangat meningkatkan nilai jangka panjang dengan menunjukkan mengapa ini adalah solusi yang baik untuk masalah ini dan akan membuatnya lebih bermanfaat untuk pembaca masa depan dengan lainnya, pertanyaan-pertanyaan serupa. Harap edit jawaban Anda untuk menambahkan beberapa penjelasan, termasuk asumsi yang Anda buat.
Abdelilah El Aissaoui