Parçaları kullanarak arka yığını temizleme


244

Android uygulamamı peteklemek için taşıdım ve parçaları kullanmak için büyük bir refactor yaptım. Önceki sürümümde, Ana Ekran düğmesine bastığımda ACTIVITY_CLEAR_TOParka yığını sıfırlamak için bir yapardım .

Şimdi uygulamam sadece birden fazla parçalı tek bir Etkinlik, bu yüzden Ana Sayfa düğmesine bastığımda içindeki parçalardan birini değiştiriyorum. Nasıl kullanmak zorunda kalmadan sırtıma yığını temizleyebilirsiniz startActivityile ACTIVITY_CLEAR_TOPbayrak?


Arka istif kullanmaktan kaçının! genel verimlilik ile gerçekten yardımcı olmaz! her gitmek istediğinizde düz değiştirme () veya daha iyi kaldırma / ekleme kullanın! Benim yazı kontrol stackoverflow.com/questions/5802141/...
stack_ved

Yanıtlar:


430

Burada benzer bir şey yayınladım

Joachim'in cevabından Dianne Hackborn'dan:

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

Ben sadece kullanarak sona erdi:

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

Ama aynı şekilde aşağıdakileri de kullanabilirdi:

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

Hangi tüm devletleri adlandırılmış olana kadar açılır. Daha sonra parçayı istediğiniz şeyle değiştirebilirsiniz


8
Geri düğmesine bir veya daha fazla kez basmakla eşdeğerdir, bu nedenle şu anda görünür olan parçayı değiştirir. (En azından denediğimde)
Peter Ajtai

7
Peter ile aynı sorunu yaşıyorum. Çok sayıda etkisi olan, onların içinden geçmesini sağlamak yerine tüm parçaları temizlemek istiyorum. Örneğin, ihtiyacınız olmayan yaşam döngüsü olaylarını, her parçayı yığının üstünden sırayla patlatarak vuracaksınız.
Brian Griffey

233
En üste gitmek için şunu kullanın: fragmentManager.popBackStack (null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
Warpzit

53
Değeri için, fragmentManager kullanarak. popBackStackImmediate (null, FragmentManager.POP_BACK_STACK_INCLUSIVE); fragman animasyonlarının yürütülmesini engellediğinden benim için daha da iyi çalıştı
roarster

17
Bu düzgün çalışmaz - aradaki her parçanın onStart çağrısını tetikler
James

165

@ Warpzit'in yorumuna cevap vermek ve başkalarının bulmasını kolaylaştırmak için.

kullanın:

fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);

14
Ben bu şekilde backstack tüm parçaları haşhaş AppCompatActivity kullanırken son v7-appCompat kütüphanesinde kırılmış olduğuna inanıyorum. Uygulamamı en son v7-appCompat kitaplığına (21.0.0) güncelledikten ve yeni AppCompatActivity'yi genişlettikten sonra, parçaları yukarıdaki şekilde patlatmak FragmentManager'ın backstack kaydında bazı parçaları bırakıyor. Bunu kullanmamanızı tavsiye ederim.
dell116

PopBackStackImmediate kullanıyor olabilir.
Kannan_SJD

38

İlgili tüm taraflara gereken saygıyla; Kaçınızın basit bir parça ile tüm parça arka yığınını temizleyebildiğini görmek beni çok şaşırttı

fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);

Android belgelerine göre ( nameiddia ile ilgili - iddia edilen çalışma tekliflerinde "boş").

Boşsa, yalnızca en üst durum açılır

Şimdi, belirli uygulamalarınız hakkında bilgi sahibi olmadığımı fark ettim (belirli bir zamanda arka yığında kaç girişiniz olduğu gibi), ancak iyi tanımlanmış bir beklerken kabul ettiğim cevapta tüm paramı bahse girerim çok çeşitli cihaz ve satıcılarda davranış:

(referans olarak, bununla birlikte bir şey)

FragmentManager fm = getFragmentManager(); // or 'getSupportFragmentManager();'
int count = fm.getBackStackEntryCount();
for(int i = 0; i < count; ++i) {    
    fm.popBackStack();
}

4
benim için her pop sizi dahili olarak her parçanın onCreateView'e götürdüğü için değildi . Bazı kaynaklarda bir NPE alacağım. Ancak fm.popBackStack (null, FragmentManager.POP_BACK_STACK_INCLUSIVE); basitçe tüm backstack'i öldürdü.
sud007

1
Döngü kullanarak açılırken CreateCreateView çağrılarını nasıl atlayacağınıza dair herhangi bir bilgi var mı?
Ayush Goyal

En üstteki parçanın (null) temizlenmesi, arka yığında ondan sonra gelen tüm parçaları temizler.
2b77bee6-5445-4c77-b1eb-4df3e5

18

Benim için ve döngü kullanmadan kolay bir şekilde çalışır:

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

17

Kabul edilen cevap benim için yeterli değildi. Kullanmak zorunda kaldım:

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

2
Bu farklı bir cevapta belirtildi, ancak not edildiğinden emin olmak için: Yığının tamamını böyle bir döngüde açarsanız, yığının başlangıcı ve bitişi arasındaki her Parça için yaşam döngüsü yöntemlerini tetikleyeceksiniz. . Bu uygulamanın çoğu kullanım durumunda istenmeyen sonuçlara yol açma şansı yüksektir. Ayrıca popBackStackImmediate(), işlemi eşzamanlı olarak gerçekleştirdiğine, genel olarak kötü tavsiye edildiğine de dikkat çekmek gerekir.
Damien Diehl

16

Döngüsüz backstack'i temizle

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

Burada ad addToBackStack () parametresidir

getSupportFragmentManager().beginTransaction().
                .replace(R.id.container, fragments.get(titleCode))
                .addToBackStack(name)

u .fragment yığınını değiştirseniz bile canlı olacak ama görünmeyecek
Asthme

8

Sadece eklemek istedim: -

Aşağıdakileri kullanarak backstack'ten dışarı çıkma

fragmentManager.popBackStack ()

parçaları işlemden kaldırmakla ilgilidir, parçayı ekrandan kaldıramaz. İdeal olarak, sizin tarafınızdan görülmeyebilir, ancak birbiri üzerine yığılmış iki veya üç parça olabilir ve arka tuşa basıldığında UI dağınık, yığılmış görünebilir.

Sadece basit bir örnek alarak: -

Diyelim ki fragmentmanager.replace () kullanarak Fragmnet B yükleyen bir fragmentA'ya sahipsiniz ve sonra bu işlemi kaydetmek için addToBackStack yapıyoruz. Böylece akış: -

ADIM 1 -> FragmentA-> FragmentB (FragmentB'ye geçtik, ancak A Parçası arka planda, görünür değil).

Şimdi fragmentB'de bir iş yapıyorsunuz ve Save düğmesine basınız - ki bu kaydedildikten sonra fragmentA'ya geri dönmelidir.

ADIM 2-> FragmentB'yi kaydettikten sonra, FragmentA'ya geri dönüyoruz.

ADIM 3 -> Çok yaygın bir hata ... Parça B'de fragmentA ile fragment Manager.replace () fragmentB yapacağız.

Ama gerçekte olan şey, FragmentB'nin yerine F Parçası A yüklüyoruz. Şimdi iki FragmentA var (biri STEP-1'den diğeri bu STEP-3'ten).

İki F Parçası örneği birbirinin üzerine istiflenebilir, bu görünmeyebilir, ancak oradadır.

Dolayısıyla, backstack'ı yukarıdaki yöntemlerle temizlesek bile, işlem temizlenir, ancak gerçek parçalar değil. İdeal olarak böyle bir durumda, kaydet düğmesine bastığınızda sadece fm.popBackStack () veya fm.popBackImmediate () yaparak fragmentA'ya geri dönmeniz gerekir. .

Bu yüzden doğru Step3-> fm.popBackStack (), zaten bellekte olan fragmentA'ya geri döner.


3

Okuma belgelerine ve parça kimliği ne okuyan, sadece yığın indeksi olmak bu eserlerin yüzden görünüyor:

fragmentManager.popBackStackImmediate(0, FragmentManager.POP_BACK_STACK_INCLUSIVE);

Sıfır (0 ), yığının en altındadır, bu nedenle ona dahil olmak, yığını temizler.

CAVEAT: Yukarıdakiler benim programımda çalışıyor olsa da, FragmentManager belgeleri aslında kimliğin yığın dizini olduğunu asla belirtmediği için biraz tereddüt ediyorum. Olması mantıklıdır ve tüm hata ayıklama günlüklerim bu kadar çıplak, ama belki de bazı özel durumlarda değil mi? Biri bunu şu ya da bu şekilde onaylayabilir mi? Öyleyse, yukarıdaki en iyi çözümdür. Değilse, alternatif budur:

while(fragmentManager.getBackStackEntryCount() > 0) { fragmentManager.popBackStackImmediate(); }

1
fragmentManager..getBackStackEntryAt(0).getId()0 yerine kullanmaya ne dersiniz ? Bu, backstack giriş kimlikleri yığın dizininden farklı bir noktada olsa bile çalışmalıdır.
ChristophK

3

Sadece bu yöntemi kullanın ve Backstake parçalarını kaldırmamız gereken Context & Fragment etiketini iletin.

kullanım

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();
    }
}

2

Merhaba ~ Çok daha iyi bir çözüm buldum: 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);
    }
}

2
Lütfen yanıtınızı bu çözümün neden daha iyi olduğu ile genişletin.
Simon.SA

SDK'nın sağladığı mekanizmayı kullanır ve bazı npe sorunlarına neden olmaz.
Chenxi

1

Bu şekilde çalıştım:

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

1

Benim için çalışıyor, şunu deneyin:

public void clearFragmentBackStack() {
        FragmentManager fm = getSupportFragmentManager();
        for (int i = 0; i < fm.getBackStackEntryCount() - 1; i++) {
            fm.popBackStack();
        }
    }

0
    private void clearBackStack(){
        SupportFragmentManaer fm = getSupportFragmentManager();
        fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
    }

Bu yönteme çağrı çok düzgün olurdu.

  1. Döngü gerekmez.
  2. Animasyonu fragmanlarda kullanıyorsanız, çok fazla animasyon gösterilmez. Ama döngü kullanmak.

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;
}

Sınırlı ve anında yardım sağlayabilecek bu kod snippet'i için teşekkür ederiz. Bir Doğru bir açıklama ölçüde bu soruna iyi bir çözüm olmasının nedeni göstererek uzun vadeli değerini artıracak ve diğer benzer sorularla gelecek okuyucularına daha kullanışlı bir hale getirecektir. Yaptığınız varsayımlar dahil bazı açıklamalar eklemek için lütfen yanıtınızı düzenleyin .
Abdelilah El Aissaoui
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.