Derinlemesine iç içe geçmiş bir yığın bırakırken Parçalı arka yığını temizlemenin doğru yolu bu mu?


130

Parçaları uygulamak için Android Uyumluluk kitaplığını kullanıyorum ve mizanpaj örneğini, bir parçanın başka bir parçayı çalıştıran bir düğme içerecek şekilde genişlettim.

Soldaki seçim bölmesinde 5 seçilebilir öğe var - A B C D E.

Her biri FragmentTransaction:replaceayrıntılar bölmesinde bir parça (yol ) yükler -a b c d e

Şimdi , ayrıntılar bölmesinde ebaşka bir parça yükleyen bir düğme içerecek şekilde genişlettim e1. Bunu parçanın eonClick yönteminde şu şekilde yaptım :

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

Aşağıdaki seçimleri yaparsam:

E - e - e1 - D - E

Daha sonra parça eayrıntılar bölmesindedir. Bu iyi ve istediğim şey. Ancak, backbu noktada düğmeye basarsam hiçbir şey yapmıyor. İki kez tıklamam gerekiyor çünkü e1hala yığında. Ayrıca etrafa tıkladıktan sonra onCreateView'da boş bir işaretçi istisnası aldım:

Bu sorunu 'çözmek' için her zaman aşağıdakileri ekledim A B C D E seçildiğinde :

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

Bunun doğru çözüm olup olmadığını veya farklı bir şey yapmam gerekip gerekmediğini merak mı ediyorsunuz?

Yanıtlar:


252

Amaçlanan davranışa bağlı olarak bunu yapmanın birkaç yolu vardır, ancak bu bağlantı size en iyi çözümleri sunmalı ve şaşırtıcı olmayan bir şekilde Dianne Hackborn'dan

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

Esasen aşağıdaki seçeneklere sahipsiniz

  • İlk arka yığın durumunuz için bir ad kullanın ve kullanın FragmentManager.popBackStack(String name, FragmentManager.POP_BACK_STACK_INCLUSIVE).
  • Arka yığındaki ilk girişin kimliğini almak için FragmentManager.getBackStackEntryCount()/ öğesini kullanın getBackStackEntryAt().getId()ve FragmentManager.popBackStack(int id, FragmentManager.POP_BACK_STACK_INCLUSIVE).
  • FragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE) tüm arka yığını patlatması gerekiyor ... Bunun için belgelerin sadece yanlış olduğunu düşünüyorum. (Aslında sanırım geçtiğiniz durumu kapsamıyor POP_BACK_STACK_INCLUSIVE),

Ne anlama geliyor? FragmentManager.getBackStackEntryCount () / getBackStackEntryAt (). GetId ()
dannyroa

4
2. benim için çalıştı. Tüm yığını temizlemek için anlamı: getSupportFragmentManager (). PopBackStack (getSupportFragmentManager (). GetBackStackEntryAt (0) .getId (), FragmentManager.POP_BACK_STACK_INCLUSIVE);
NickL

@JorgeGarcia, popbackstack'ten sonra parçamızı eski olanı yeniden başlatmadan bitirmemiz mümkün.
duggu

PopBackStack () eşzamansız olduğu için popBackStackImmediate () sürümü de vardır, yani temizleme işlemi tam olarak yöntemi çağırdığınız anda gerçekleşmez.
Genc

6
Grubun spam olarak yasaklandığını iddia ediyor ve bağlantıya erişemiyorum :( başka yerde kaynağa sahip olan var mı?
EpicPandaForce

61

Tüm yığın girişlerini açmak istemiyorsanız diğer temiz çözüm ...

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

Bu, önce yığını temizleyecek ve ardından yeni bir parça yükleyecektir, böylece herhangi bir noktada yığında yalnızca tek bir parçaya sahip olacaksınız


1
Bu çok kötü: getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);Bir değiştirmeden önce () Fragman arama yüklenirken çünkü onCreateView(), onActivityCreated()vb geri yükleme ve Fragment anında kötü Destroing. Fragment, örneğin bir alıcı kaydedebilir. Bu performansı etkiler.
VasileM

@VasileM, detaylı olarak anlatır mısınız? Hangi durumlarda kötüdür? Zaman uyumsuz davranışı yüzünden FragmentTransactionmi? Yalnızca yanlış parça yığınının kötü performansı mı var?
CoolMind

27

Joachim cevabı sayesinde , sonunda tüm arka yığın girişlerini temizlemek için kodu kullanıyorum.

// 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 */

18
Neden burada bir döngü kullanıyorsunuz? Benim için FragmentManager.popBackStack (null, FragmentManager.POP_BACK_STACK_INCLUSIVE) tüm geri yığın girişlerini temizledi ...
Marek

3
@Marek, bazen tüm fragmanların kaldırılması gerekmediği için bunun için bir döngü uygundur.
CoolMind

1
@CoolMind, bu bana hala mantıklı gelmiyor. popBackStack(backStackId, INCLUSIVE)tüm parçaları (durumları) backStackId'e geri döndürecektir, bu nedenle patlayacağınız en düşük seviyeye ulaştığınızda i, tüm yüksek olanlar aynı anda patlatılmalıdır. Öyleyse bir döngünün amacı nedir?
LarsH

@LarsH, haklısın. Stackoverflow.com/a/59158254/2914140 adresine bakın . Diğer fragmanları gerekli etikete yerleştirmek için önce fragmanı addToBackStack ( tag ) ile eklemeliyiz .
CoolMind

7

Backstack'i temizlemek için çok araştırma yaptım ve sonunda Transaction BackStack ve yönetimini görüyorum . İşte benim için en çok işe yarayan çözüm.

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

Yukarıdaki yöntem, arkadaki tüm işlemlerin üzerinden geçer ve bunları birer birer kaldırır.

Not: Yukarıdaki kod bazen çalışmıyor ve bu kod nedeniyle ANR ile karşılaşıyorum , bu yüzden lütfen bunu denemeyin.

Aşağıdaki yöntemi güncelle , bu "adın" tüm fregmentini backstack'ten kaldırır.

FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.popBackStack("name",FragmentManager.POP_BACK_STACK_INCLUSIVE);
  • isim Eğer boş değilse, bu aranacak önceki geri durumun adıdır; bulunursa, o duruma kadar olan tüm durumlar açılır.
  • POP_BACK_STACK_INCLUSIVE bayrağı, adlandırılmış durumun kendisinin atılıp atılmadığını kontrol etmek için kullanılabilir. Boşsa, yalnızca üst durum açılır.

Neden birer birer çıkarıyorsun anlamıyorum. Diğer çözümler yerine bu çözümü seçmenizin bir nedeni var mı? Hepsini bir kerede kaldırmak yerine birer birer kaldırmanın bir nedeni var mı?
miva2

Hiçbir yöntemin thair bir kez bkz en backstack kaldırmak için developer.android.com/reference/android/app/...
Lokesh

3

While döngüsünü kullananlara benzer bir kod kullanıyorum ama her döngüde girdi sayısını çağırıyorum ... bu yüzden sanırım biraz daha yavaş

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

0

Yazılı olarak backstack kapalı fragman pop Nasıl tarafından Larsh burada, biz (specifical etiketine üst menüden birkaç parçalarını pop birlikte etiketli bir parçası olan bu yöntemi kullanarak):

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

Parçanızın etiketini "frag" ile değiştirin. Önce parçayı backstack'e eklememiz gerektiğini unutmayın:

fragmentTransaction.addToBackStack("frag")

İle parçalar eklersek addToBackStack(null), parçaları bu şekilde açmayız.


-4
    // pop back stack all the way
    final FragmentManager fm = getSherlockActivity().getSupportFragmentManager();
    int entryCount = fm.getBackStackEntryCount(); 
    while (entryCount-- > 0) {
        fm.popBackStack();
    }
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.