backstack'teki en son parçayı al


104

Backstack'e eklenen en son parça örneğini nasıl elde edebilirim (parça etiketini ve kimliğini bilmiyorsam)?

FragmentManager fragManager = activity.getSupportFragmentManager();
FragmentTransaction fragTransacion = fragMgr.beginTransaction();

/****After add , replace fragments 
  (some of the fragments are add to backstack , some are not)***/

//HERE, How can I get the latest added fragment from backstack ??

Yanıtlar:


156

API seviyesi 14'te tanıtılan getName()yöntemi kullanabilirsiniz FragmentManager.BackStackEntry. Bu yöntem, Parçayı backstack'e eklediğinizde kullandığınız etiketi döndürür addTobackStack(tag).

int index = getActivity().getFragmentManager().getBackStackEntryCount() - 1
FragmentManager.BackStackEntry backEntry = getFragmentManager().getBackStackEntryAt(index);
String tag = backEntry.getName();
Fragment fragment = getFragmentManager().findFragmentByTag(tag);

Parçayı arka desteye şu şekilde eklediğinizden emin olmalısınız:

fragmentTransaction.addToBackStack(tag);

24
Etikete göre parça bulmak için aynı etiketle eklenmesi / değiştirilmesi gerekir. FragmentTransaction.add(int containerViewId, Fragment fragment, String tag)veya FragmentTransaction.replace(int containerViewId, Fragment fragment, String tag) doc
Saqib

3
Bununla ilgili sorun, arka yığında iki kez bir fragmanınız varsa, sahip olduğunuz tek şey indeks veya backstackentry varlığı olduğunda belirli bir parçayı geri alamazsınız.
Justin

14
stackParçaya bir pop yöntemiyle erişemezsem, buna bir demenin anlamı nedir ?
Kenny Worden

5
RTFM

1
Nedenini bilmiyorum ama findFragmentByTag, hata ayıklayıcı açıkça etiketin tamam olduğunu gösterdiğinde bile boş döndürüyor.
htafoya

49
FragmentManager.findFragmentById(fragmentsContainerId) 

işleviFragment backstack'te üste bağlantı döndürür . Kullanım örneği:

    fragmentManager.addOnBackStackChangedListener(new OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            Fragment fr = fragmentManager.findFragmentById(R.id.fragmentsContainer);
            if(fr!=null){
                Log.e("fragment=", fr.getClass().getSimpleName());
            }
        }
    });

2
Kök parçası dışındaki her parçayı arka yığına eklediğim için bu yanıt projemde iyi çalışıyor. Ancak en son eklenen parça arka yığına eklenmemişse bu yanıtın işe yaramayacağını tahmin ediyorum.
Arne Evertsson

40

Ben şahsen bu çözümlerin çoğunu denedim ve bu çalışma çözümünü buldum:

Backstack'inizdeki parça sayısını elde etmek için birkaç kez kullanılacak olan bu yardımcı programı ekleyin:

protected int getFragmentCount() {
    return getSupportFragmentManager().getBackStackEntryCount();
}

Ardından, FragmentTransaction yöntemini kullanarak parçanızı eklediğinizde / değiştirdiğinizde, parçanız için benzersiz bir etiket oluşturun (örneğin: yığınızdaki parça sayısını kullanarak):

getSupportFragmentManager().beginTransaction().add(yourContainerId, yourFragment, Integer.toString(getFragmentCount()));

Son olarak, bu yöntemle arka istifinizde herhangi bir parçayı bulabilirsiniz:

private Fragment getFragmentAt(int index) {
    return getFragmentCount() > 0 ? getSupportFragmentManager().findFragmentByTag(Integer.toString(index)) : null;
}

Bu nedenle, arka yığınınızdaki en üst parçayı getirmek, aşağıdakileri arayarak kolayca elde edilebilir:

protected Fragment getCurrentFragment() {
    return getFragmentAt(getFragmentCount() - 1);
}

Bu yardımcı olur umarım!


10

bu yardımcı yöntem yığının tepesinden parça alır:

public Fragment getTopFragment() {
    if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
        return null;
    }
    String fragmentTag = getSupportFragmentManager().getBackStackEntryAt(getSupportFragmentManager().getBackStackEntryCount() - 1).getName();
    return getSupportFragmentManager().findFragmentByTag(fragmentTag);
}

1
Teşekkürler. En zarif cevap. Kotlin severler için buraya eklendi stackoverflow.com/a/47336504/1761406
Shirane85

7

Kotlin

activity.supportFragmentManager.fragments.last()

4
Boş .lastOrNull()olması durumunda kullanmanız gerekebilir fragments.
Westy92

6

FragmentMananger'da bir parça listesi var. Bir parçayı kaldırmanın liste boyutunu küçültmediğini unutmayın (parça girişi sadece boşa döner). Bu nedenle, geçerli bir çözüm şöyle olacaktır:

public Fragment getTopFragment() {
 List<Fragment> fragentList = fragmentManager.getFragments();
 Fragment top = null;
  for (int i = fragentList.size() -1; i>=0 ; i--) {
   top = (Fragment) fragentList.get(i);
     if (top != null) {
       return top;
     }
   }
 return top;
}

2
Güvenilir değil. Üç neden: 1) Bu, yalnızca yığındakilerin değil, parça yöneticisinin bildiği tüm parçaların bir listesidir. 2) Parça yöneticisinin listenin sonuna yenilerini eklemeye devam edeceğine dair bir garanti yoktur. Elbette, bunu basit testlerde yapacak, ama ya bir parça kaldırılırsa, bir boş bırakılırsa ve bazı durumlarda parça yöneticisi bu boş yuvayı yeniden kullanmaya karar verirse? Öyle demiyorum ama hiçbir koşulda olmayacağının garantisi yok. 3) Siz veya gelecekteki bir programcı, parçaları yönetmek için ekleme / ayırma kullanmaya başlarsa, bu yığınla eşleşmeyecektir.
ToolmakerSteve

Merhaba, çözümünüz için teşekkürler ama bu güzel ve kolay değil
Muhammed Ali

Bunun çalışan bir solutuin olduğundan şüpheliyim. getFragments()kısaltılmış bir parça koleksiyonu döndürür. Belki sonuncusu görülebilir, ancak diğerleri değil.
CoolMind

5

Deepak goel'in verdiği cevap benim için işe yaramıyor çünkü ben hep null alıyorum entry.getName();

Yaptığım şey, şu şekilde parçaya bir Etiket ayarlamak:

ft.add(R.id.fragment_container, fragmentIn, FRAGMENT_TAG);

Ft, parça işlemim ve FRAGMENT_TAGetikettir. Sonra parçayı almak için bu kodu kullanıyorum:

Fragment prev_fragment = fragmentManager.findFragmentByTag(FRAGMENT_TAG);

Bu, yalnızca tüm parçaya aynı etiketi verirseniz işe yarar; bu, daha sonra belirli bir parçayı bulmak istiyorsanız iyi bir fikir değildir.
Shirane85

4

@Roghayeh hosseini (doğru) cevabını aldım ve 2017'de burada olanlar için Kotlin'de yaptım :)

fun getTopFragment(): Fragment? {
    supportFragmentManager.run {
        return when (backStackEntryCount) {
            0 -> null
            else -> findFragmentByTag(getBackStackEntryAt(backStackEntryCount - 1).name)
        }
    }
}

* Bu, bir Aktivite içinden çağrılmalıdır.

Zevk almak :)


3

getBackStackEntryAt () kullanabilirsiniz . Backstack'te etkinliğin kaç giriş tuttuğunu bilmek için getBackStackEntryCount () 'u kullanabilirsiniz.

int lastFragmentCount = getBackStackEntryCount() - 1;

11
Ama arka yığıntaki son parçayı nasıl alabilirim ?? PopBackStackEntryAt () yalnızca bir BackStackEntry örneği döndürür, parça DEĞİL
Leem.fin

evet haklısınız, ancak getId () ile geri alabileceğiniz her BackStackEntry muhafazası ve kimliği. parçayı geri almak için bu kimliği kullanabilirsiniz
Blackbelt

1
Son parçayı almak için: getBackStackEntryCount () - 1
An-droid

3
Bu cevap yanlış, arka istif girişlerinin 0 kimliğine sahip olduğunu görüyorum, bu yüzden parçayı kimliğe göre alamıyorum.
Justin

1
Bu eski, ama burada dolaşan herkes için: arka yığın parçalar tutmaz, ancak parça işlemleri, bu yüzden bu yanıt yanlış
maciekjanusz

3

Deepak Goel'in cevabına bir şeyler ekleyeceğim, çünkü ben dahil pek çok insan onun yöntemini kullanarak boşa çıkıyor. Görünüşe göre, arka yığına bir parça eklediğinizde etiketin çalışmasını sağlamak için bunu şu şekilde yapmalısınız:

getSupportFragmentManager.beginTransaction().replace(R.id.container_id,FragmentName,TAG_NAME).addToBackStack(TAG_NAME).commit();

Aynı etiketi iki kez eklemeniz gerekir.

Yorum yapardım ama 50 itibarım yok.


şimdi 50 var :)
davidbilla

2

Kendi arka yığını tutun: myBackStack. Eğer gibi Addbir parçası FragmentManager, aynı zamanda onu eklemek myBackStack. Gelen onBackStackChanged()gelen pop myBackStackuzunluğu daha büyük olduğu zaman getBackStackEntryCount.


2

Görünüşe göre bir şeyler daha iyiye doğru değişti, çünkü aşağıdaki kod benim için mükemmel çalışıyor, ancak bunu zaten verilen cevaplarda bulamadım.

Kotlin:

supportFragmentManager.fragments[supportFragmentManager.fragments.size - 1]

Java:

getSupportFragmentManager().getFragments()
.get(getSupportFragmentManager().getFragments().size() - 1)

2

Kullanıyorsanız addToBackStack()aşağıdaki kodu kullanabilirsiniz.

List<Fragment> fragments = fragmentManager.getFragments(); activeFragment = fragments.get(fragments.size() - 1);


1

Aslında yığına eklenen en son parça yoktur, çünkü tek bir işlemde yığına birkaç parça veya parça ekleyebilir veya yeni bir tane eklemeden parçaları kaldırabilirsiniz.

Gerçekten bir parça yığınına sahip olmak ve yığındaki indeksine göre bir parçaya erişebilmek istiyorsanız, arka yığınında bir soyutlama katmanınız olsa iyi FragmentManagerolur. İşte bunu nasıl yapabileceğiniz:

public class FragmentStackManager {
  private final FragmentManager fragmentManager;
  private final int containerId;

  private final List<Fragment> fragments = new ArrayList<>();

  public FragmentStackManager(final FragmentManager fragmentManager,
      final int containerId) {
    this.fragmentManager = fragmentManager;
    this.containerId = containerId;
  }

  public Parcelable saveState() {
    final Bundle state = new Bundle(fragments.size());
    for (int i = 0, count = fragments.size(); i < count; ++i) {
      fragmentManager.putFragment(state, Integer.toString(i), fragments.get(i));
    }
    return state;
  }

  public void restoreState(final Parcelable state) {
    if (state instanceof Bundle) {
      final Bundle bundle = (Bundle) state;
      int index = 0;
      while (true) {
        final Fragment fragment =
            fragmentManager.getFragment(bundle, Integer.toString(index));
        if (fragment == null) {
          break;
        }

        fragments.add(fragment);
        index += 1;
      }
    }
  }

  public void replace(final Fragment fragment) {
    fragmentManager.popBackStackImmediate(
        null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
    fragmentManager.beginTransaction()
        .replace(containerId, fragment)
        .addToBackStack(null)
        .commit();
    fragmentManager.executePendingTransactions();

    fragments.clear();
    fragments.add(fragment);
  }

  public void push(final Fragment fragment) {
    fragmentManager
        .beginTransaction()
        .replace(containerId, fragment)
        .addToBackStack(null)
        .commit();
    fragmentManager.executePendingTransactions();

    fragments.add(fragment);
  }

  public boolean pop() {
    if (isEmpty()) {
      return false;
    }

    fragmentManager.popBackStackImmediate();

    fragments.remove(fragments.size() - 1);
    return true;
  }

  public boolean isEmpty() {
    return fragments.isEmpty();
  }

  public int size() {
    return fragments.size();
  }

  public Fragment getFragment(final int index) {
    return fragments.get(index);
  }
}

Yerine ekleme ve arayarak parçaları kaldırma Şimdi FragmentManagerdoğrudan, kullanmak gerekir push(), replace()vepop() yöntemleri FragmentStackManager. Ve sadece arayarak en üstteki parçaya erişebileceksiniz stack.get(stack.size() - 1).

Ama korsanlardan hoşlanıyorsanız, benzer şeyler yapmanın başka yollarına ihtiyacım var. Söylemem gereken tek şey, bu korsanların yalnızca destek parçalarıyla çalışacağıdır.

İlk hack, sadece tüm aktif parçaların parça yöneticisine eklenmesini sağlamaktır. Parçaları tek tek değiştirir ve yığından çıkarırsanız, bu yöntem en üstteki parçayı döndürür:

public class BackStackHelper {
  public static List<Fragment> getTopFragments(
      final FragmentManager fragmentManager) {
    final List<Fragment> fragments = fragmentManager.getFragments();
    final List<Fragment> topFragments = new ArrayList<>();

    for (final Fragment fragment : fragments) {
      if (fragment != null && fragment.isResumed()) {
        topFragments.add(fragment);
      }
    }

    return topFragments;
  }
}

İkinci yaklaşım, olay daha hack'lidir ve addToBackStackçağrılan son işlemde eklenen tüm parçaları almanıza izin verir :

package android.support.v4.app;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class BackStackHelper {
  public static List<Fragment> getTopFragments(
      final FragmentManager fragmentManager) {
    if (fragmentManager.getBackStackEntryCount() == 0) {
      return Collections.emptyList();
    }

    final List<Fragment> fragments = new ArrayList<>();

    final int count = fragmentManager.getBackStackEntryCount();
    final BackStackRecord record =
        (BackStackRecord) fragmentManager.getBackStackEntryAt(count - 1);
    BackStackRecord.Op op = record.mHead;
    while (op != null) {
      switch (op.cmd) {
        case BackStackRecord.OP_ADD:
        case BackStackRecord.OP_REPLACE:
        case BackStackRecord.OP_SHOW:
        case BackStackRecord.OP_ATTACH:
          fragments.add(op.fragment);
      }
      op = op.next;
    }

    return fragments;
  }
}

Lütfen bu durumda bu sınıfı android.support.v4.apppakete koymanız gerektiğini unutmayın .


0

Veya içeriklerine karşılık gelen parçaları eklerken bir etiket ekleyebilir ve son eklenen parça etiketini tutmak ve bu parçayı byTag () almak için basit statik String alanını kullanabilirsiniz (ayrıca onSaveInstanceState (Bundle) yöntemindeki etkinlik örneği paketine kaydedebilirsiniz) ihtiyaç duyduğunuz her an ...


0

En yüksek (Deepak Goel) cevap benim için pek işe yaramadı. Her nasılsa etiket doğru şekilde eklenmemiş.

Sonunda parçanın kimliğini akış yoluyla gönderdim (amaçları kullanarak) ve doğrudan parça yöneticisinden geri aldım.

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.