Parça yöneticisi

FragmentManager uygulamanızın parçalarında işlem yapmaktan sorumlu sınıf eklemek, kaldırmak veya değiştirmek ve arka gruba eklemek gibi.

FragmentManager Jetpack Navigation kitaplığıyla Sizin adınıza FragmentManager. Ancak parçaları kullanan tüm uygulamalar FragmentManager ile ne ifade ettiğini bilmek önemlidir; o yüzden nasıl işlediğini tartıştık.

Bu sayfada ele alınan konular:

  • FragmentManager uygulamasına nasıl erişilir?
  • Etkinlikleriniz ve parçalarınıza göre FragmentManager rolü.
  • Arka yığını FragmentManager ile yönetme.
  • Parçalarınıza veri ve bağımlılık sağlama.

FragmentManager'a erişme

FragmentManager öğesine bir etkinlikten veya parçadan erişebilirsiniz.

FragmentActivity ve alt sınıfları (örneğin, AppCompatActivity, şurası aracılığıyla FragmentManager: getSupportFragmentManager() yöntemidir.

Parçalar, bir veya daha fazla alt parçayı barındırabilir. İç mekan olursa, bunu yöneten FragmentManager öğesine bir referans alabilirsiniz parçanın alt öğelerini getChildFragmentManager() FragmentManager ana makinesine erişmeniz gerekiyorsa şunu kullanabilirsiniz: getParentFragmentManager()

Aşağıda, müşteri ilişkileri yönetimi ile parçalar, ana makineleri ve ilişkili FragmentManager örnekleri her biri için geçerli.

arasındaki ilişkileri gösteren iki kullanıcı arayüzü düzeni örneği
            parçalar ve bunların ev sahibi etkinlikleri
Şekil 1. Şunu gösteren iki kullanıcı arayüzü düzeni örneği: arasındaki ilişkiyi gözlemler.

Şekil 1'de her biri tek bir etkinlik ana makinesine sahip olan iki örnek gösterilmektedir. İlgili içeriği oluşturmak için kullanılan her ikisinde de barındırma etkinliği, üst düzey gezinmeyi kullanıcıya BottomNavigationView ana makine parçasını farklı bir öğeyle değiştirmekten sorumlu ekleyebilirsiniz. Her ekran ayrı bir parça olarak uygulanır.

Örnek 1'deki ana makine parçası, bölünmüş görünüm oluşturabilirsiniz. Örnek 2'deki ana makine parçası, bir kaydırma görünümü.

Bu kurulumu göz önünde bulundurarak her barındırıcının bir FragmentManager sahibi olduğunu düşünebilirsiniz bununla ilişkilendirilir. Bu işlem supportFragmentManager arasındaki özellik eşlemeleri ile birlikte şekil 2, parentFragmentManager ve childFragmentManager.

her ana makinenin kendisiyle ilişkilendirilmiş FragmentManager'ı vardır
            parçalarını yöneten
Şekil 2. Her ana makinenin kendine ait Bunu yöneten FragmentManager ile ilişkilendirilmiş parçalarını anlatır.

Referansta bulunulacak uygun FragmentManager özelliği, öğenin nerede olduğuna bağlıdır çağrı sitesi, parça hiyerarşisinde ve parça yöneticisinin içinde bulunduğu bilgileri de içerebilir.

FragmentManager için referans aldıktan sonra, bunu şu amaçlarla kullanabilirsiniz: kullanıcıya gösterilen parçaları manipüle eder.

Alt parçalar

Genel anlamda, uygulamanız tek veya az bir sayıdan oluşur her bir aktivite temsil eder ve bir grup ekran vardır. Etkinlik, ziyaret edilmesi gereken bir yere üst düzey gezinme ve ViewModel nesneleri ile diğer görünüm durumlarını kapsamak için bir yer yardımcı olur. Bir parça, sayfanızdaki uygulamasını indirin.

Birden çok parçayı aynı anda (örneğin, bölünmüş görünümde) göstermek istiyorsanız bir kontrol paneli kullanıyorsanız, hedef parçayı ve alt parça yöneticisini içerir.

Alt parçaların diğer kullanım alanları şunlardır:

  • Slaytları inceleyin, bir alt öğe serisini yönetmek için üst parçada ViewPager2 kullanma parça görünümleri.
  • İlgili ekran grubu içinde alt gezinme.
  • Jetpack Navigation, alt parçaları ayrı hedefler olarak kullanır. etkinlik, tek bir üst NavHostFragment barındırıyor ve alanını dolduruyor kullanıcılar gezindikçe farklı alt hedef parçalarıyla en iyi şekilde yararlanabilirsiniz.

FragmentManager'ı kullanma

FragmentManager, parça arka yığınını yönetir. Çalışma zamanında, FragmentManager, ekleme veya kaldırma gibi geri yığın işlemleri gerçekleştirebilir parçalar. Her bir değişiklik kümesi bir araya getirilmiş tek bir birim olarak FragmentTransaction. Parça işlemleri hakkında daha ayrıntılı bir tartışma için parça işlemleri rehberini inceleyin.

Kullanıcı, cihazındaki Geri düğmesine dokunduğunda veya telefon ettiğinizde FragmentManager.popBackStack() en üstteki parça işlem yığından dışarı çıkar. Daha fazla parça yoksa işlemleri içerir ve alt parçalar kullanmıyorsanız Geri köprü görevi görebilir. Alt parçalar kullanıyorsanız alt ve kardeş parçalar için özel hususlar.

Aradığınızda addToBackStack() işlemde herhangi bir sayıda olabilir. birden çok parça ekleme veya parçaları birden fazla parçada değiştirme gibi işlemler container'lar.

Arka yığın patladığında, tüm bu işlemleri tek bir atomik etki olarak tersini yapar. Ancak, popBackStack() görüşmesinden önce ek işlemler gerçekleştirdiyseniz ve Bu işlemler için addToBackStack() kullanılmadı yapmayın. Bu nedenle, tek bir FragmentTransaction içinde arka yığınını etkilemeyen işlemler arasında boşluk eklemek.

İşlem gerçekleştirme

Düzen kapsayıcısı içinde bir parçayı görüntülemek için FragmentManager öğesini kullanın FragmentTransaction oluşturun. İşlemin içinde şunları yapabilirsiniz: gerçekleştir add() veya replace() oluşturmanız gerekir.

Örneğin, basit bir FragmentTransaction şöyle görünebilir:

Kotlin

supportFragmentManager.commit {
   replace<ExampleFragment>(R.id.fragment_container)
   setReorderingAllowed(true)
   addToBackStack("name") // Name can be null
}

Java

FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
    .replace(R.id.fragment_container, ExampleFragment.class, null)
    .setReorderingAllowed(true)
    .addToBackStack("name") // Name can be null
    .commit();

Bu örnekte, ExampleFragment, herhangi bir parçanın tarafından tanımlanan düzen kapsayıcısında R.id.fragment_container kimliği. Parçanın sınıfını replace() yöntemi, FragmentManager tarafından örneklenmek için FragmentFactory. Daha fazla bilgi için Parçalarınıza bağımlılık sağlama bölümüne bakın. bölümüne bakın.

setReorderingAllowed(true) işleme dahil olan parçaların durum değişikliklerini optimize eder düzgün şekilde çalışmasını sağlayacaktır. Daha fazla bilgi için animasyonlar ve geçişlerle gezinmeyi görmek için Parça işlemleri ve Animasyonları kullanarak parçalar arasında gezinme.

Telefon etme addToBackStack() işlemi arka yığına kaydeder. Kullanıcı daha sonra dokunun ve Geri düğmesine dokunarak önceki parçayı geri getirin düğmesini tıklayın. Tek bir öğede birden fazla parça eklediyseniz veya kaldırdıysanız geri yığını olduğunda, tüm bu işlemler patlatılır. addToBackStack() çağrısında sağlanan isteğe bağlı ad, belirli bir işleme geri dönme seçeneği ile popBackStack()

Aşağıdaki özelliklere sahip bir işlem gerçekleştirirken addToBackStack() işlevini çağırmazsanız bir parçayı kaldırırsa, kaldırılan parça işlem yapılır ve kullanıcı bu işleme geri dönemez. Şu durumda: bir parçayı kaldırırken addToBackStack() komutunu çağırırsa parça, yalnızca STOPPED ve daha sonra RESUMED olarak görünür. Görünümü kaldırılır. Daha fazla bilgi için bkz. Parça yaşam döngüsü.

Mevcut bir parçayı bul

Bir düzen kapsayıcısı içindeki geçerli parçaya referans alabilirsiniz - findFragmentById(). Aşağıdaki durumlarda, verilen kimliğe göre bir parçayı aramak için findFragmentById() kullanın: XML'den veya kapsayıcı kimliği tarafından şişirilmiş FragmentTransaction. Aşağıda bununla ilgili bir örnek verilmiştir:

Kotlin

supportFragmentManager.commit {
   replace<ExampleFragment>(R.id.fragment_container)
   setReorderingAllowed(true)
   addToBackStack(null)
}
...
val fragment: ExampleFragment =
        supportFragmentManager.findFragmentById(R.id.fragment_container) as ExampleFragment

Java

FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
    .replace(R.id.fragment_container, ExampleFragment.class, null)
    .setReorderingAllowed(true)
    .addToBackStack(null)
    .commit();
...
ExampleFragment fragment =
        (ExampleFragment) fragmentManager.findFragmentById(R.id.fragment_container);

Alternatif olarak, bir parçaya benzersiz bir etiket atayabilir ve şunu kullanarak referansta bulun: findFragmentByTag(). Şunu yaptığınız parçalarda android:tag XML özelliğini kullanarak bir etiket atayabilirsiniz: düzeninizin içinde veya add() ya da replace() sırasında tanımlandığı gibi işlemi FragmentTransaction içinde yapmanız gerekir.

Kotlin

supportFragmentManager.commit {
   replace<ExampleFragment>(R.id.fragment_container, "tag")
   setReorderingAllowed(true)
   addToBackStack(null)
}
...
val fragment: ExampleFragment =
        supportFragmentManager.findFragmentByTag("tag") as ExampleFragment

Java

FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
    .replace(R.id.fragment_container, ExampleFragment.class, null, "tag")
    .setReorderingAllowed(true)
    .addToBackStack(null)
    .commit();
...
ExampleFragment fragment = (ExampleFragment) fragmentManager.findFragmentByTag("tag");

Alt ve kardeş parçalar için özel noktalar

Parça arka yığınını yalnızca bir FragmentManager kontrol edebilir . Uygulamanız veya uygulamanız alt parçalar kullanıyorsa FragmentManager, uygulamanızın birincil gezinme bölümünü işleyecek şekilde atandı.

Bir parça işleminin içinde birincil gezinme parçasını tanımlamak için: şunu ara: setPrimaryNavigationFragment() yöntemini kullanan parçanın örneğini childFragmentManager birincil denetime sahiptir.

Gezinme yapısını, etkinliği içeren bir dizi katman olarak düşünün. en dış katman olarak ayarlayıp, altındaki her alt parça katmanını sarmalar. Her katmanın tek bir birincil gezinme parçası vardır.

Önceki etkinliği gerçekleşirse en içteki katman gezinme davranışını kontrol eder. Bir en içteki katmanda geri açılacağı daha fazla parça işlemi yoktur, kontrolü bir sonraki katmana geçer ve bu işlem siz bu işlemi bitirene kadar ulaşabilmeniz gerekir.

İki veya daha fazla parça aynı anda görüntülendiğinde yalnızca bunlardan biri birincil gezinme parçasıdır. Parça ayarlama olarak, birincil gezinme parçası önceki olabilir. Önceki örneği kullanarak, ayrıntı parçasını birincil gezinme parçasının ataması kaldırılır.

Birden fazla arka yığını destekleme

Bazı durumlarda uygulamanızın birden fazla arka yığını desteklemesi gerekebilir. Yaygın bir Örneğin, uygulamanızda alt gezinme çubuğu kullanılıyorsa. FragmentManager izin saveBackStack() ve 12 farklı arka plana sahip birden çok yığını desteklersiniz. restoreBackStack() yöntem. Bu yöntemler, farklı feed'ler arasında farklı bir yığın geri yükleyerek büyük gruplar oluşturur.

saveBackStack(), isteğe bağlı ile popBackStack() çağrısına benzer şekilde çalışır name parametresi: patlatılır. Aradaki fark, saveBackStack() ürününün pop-up'taki tüm parçaların durumu işlemlerdir.

Örneğin, daha önce arka yığına bir parçayı aşağıda gösterildiği gibi addToBackStack() kullanarak bir FragmentTransaction uygulanması şu örneği inceleyin:

Kotlin

supportFragmentManager.commit {
  replace<ExampleFragment>(R.id.fragment_container)
  setReorderingAllowed(true)
  addToBackStack("replacement")
}

Java

supportFragmentManager.beginTransaction()
  .replace(R.id.fragment_container, ExampleFragment.class, null)
  // setReorderingAllowed(true) and the optional string argument for
  // addToBackStack() are both required if you want to use saveBackStack()
  .setReorderingAllowed(true)
  .addToBackStack("replacement")
  .commit();

Bu durumda, bu parça işlemini ve saveBackStack() numaralı telefonu arayarak ExampleFragment:

Kotlin

supportFragmentManager.saveBackStack("replacement")

Java

supportFragmentManager.saveBackStack("replacement");

Tüm özellikleri geri yüklemek için restoreBackStack() öğesini aynı name parametresiyle çağırabilirsiniz. açılan işlemler ve tüm kayıtlı parça durumları:

Kotlin

supportFragmentManager.restoreBackStack("replacement")

Java

supportFragmentManager.restoreBackStack("replacement");

Parçalarınıza bağımlılık sağlayın

Bir parça eklerken, parçayı manuel olarak örneklendirebilir ve FragmentTransaction bölümüne ekleyin.

Kotlin

fragmentManager.commit {
    // Instantiate a new instance before adding
    val myFragment = ExampleFragment()
    add(R.id.fragment_view_container, myFragment)
    setReorderingAllowed(true)
}

Java

// Instantiate a new instance before adding
ExampleFragment myFragment = new ExampleFragment();
fragmentManager.beginTransaction()
    .add(R.id.fragment_view_container, myFragment)
    .setReorderingAllowed(true)
    .commit();

Parça işlemini kaydettiğinizde parçanın örneği oluşturduğunuz örnektir. Ancak, yapılandırma değişikliği, etkinliği ve tüm parçaları yok edilir ve ardından en uygun Android kaynakları. FragmentManager tüm bunları sizin için yapar: Örnekleri yeniden oluşturur ana makineye ekler ve arka yığını yeniden oluşturur. durumu.

Varsayılan olarak, FragmentManager bir FragmentFactory çerçeve, parçanızın yeni bir örneğini örneklendirmeyi sağlar. Bu varsayılan fabrika, bağımsız değişkensiz bir oluşturucu bulmak ve çağırmak için yansıma kullanır oluşturmanız gerekir. Dolayısıyla bu varsayılan fabrikayı şu işlemler için kullanamazsınız: ve parçanıza bağımlılık sağlar. Aynı zamanda herhangi bir özel parçanızı ilk kez oluşturmak için kullandığınız kurucu kullanılmıyor varsayılan ayardır.

Parçanıza bağımlılık sağlamak veya herhangi bir özel oluşturucu; bunun yerine özel bir FragmentFactory alt sınıfı oluşturun ve ardından FragmentFactory.instantiate Daha sonra FragmentManager cihazının varsayılan fabrika ayarlarını şu değerle geçersiz kılabilirsiniz: Bu özel fabrikanız, parçalarınızı örneklendirmek için kullanılır.

Bir anahtar kelime için reklam göstermekten sorumlu bir DessertsFragment gitmeye ne dersiniz? Yoksa DessertsFragment sağlayan bir DessertsRepository sınıfına bağımlılığı vardır. doğru kullanıcı arayüzünü görüntülemek için gereken bilgileri girin.

DessertsFragment öğenizi, DessertsRepository gerektirecek şekilde tanımlayabilirsiniz örneğini oluşturur.

Kotlin

class DessertsFragment(val dessertsRepository: DessertsRepository) : Fragment() {
    ...
}

Java

public class DessertsFragment extends Fragment {
    private DessertsRepository dessertsRepository;

    public DessertsFragment(DessertsRepository dessertsRepository) {
        super();
        this.dessertsRepository = dessertsRepository;
    }

    // Getter omitted.

    ...
}

FragmentFactory basit bir şekilde uygulanması şuna benzer görünebilir: şunları içerir:

Kotlin

class MyFragmentFactory(val repository: DessertsRepository) : FragmentFactory() {
    override fun instantiate(classLoader: ClassLoader, className: String): Fragment =
            when (loadFragmentClass(classLoader, className)) {
                DessertsFragment::class.java -> DessertsFragment(repository)
                else -> super.instantiate(classLoader, className)
            }
}

Java

public class MyFragmentFactory extends FragmentFactory {
    private DessertsRepository repository;

    public MyFragmentFactory(DessertsRepository repository) {
        super();
        this.repository = repository;
    }

    @NonNull
    @Override
    public Fragment instantiate(@NonNull ClassLoader classLoader, @NonNull String className) {
        Class<? extends Fragment> fragmentClass = loadFragmentClass(classLoader, className);
        if (fragmentClass == DessertsFragment.class) {
            return new DessertsFragment(repository);
        } else {
            return super.instantiate(classLoader, className);
        }
    }
}

Bu örnekte, instantiate() geçersiz kılınarak FragmentFactory alt sınıfları yöntemini kullanarak DessertsFragment için özel parça oluşturma mantığı sağlayabilirsiniz. Diğer parça sınıfları, şunun varsayılan davranışına göre işlenir: FragmentFactory - super.instantiate().

Daha sonra, şu durumlarda kullanılacak fabrikayı MyFragmentFactory belirtebilirsiniz: oluşturmak için FragmentManager. Bu özelliği, etkinliğinizin tarihinden önce ayarlamanız gerekir. MyFragmentFactory aşağıdaki durumlarda kullanıldığından emin olmak için super.onCreate() yeniden oluşturmanıza yardımcı olur.

Kotlin

class MealActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        supportFragmentManager.fragmentFactory = MyFragmentFactory(DessertsRepository.getInstance())
        super.onCreate(savedInstanceState)
    }
}

Java

public class MealActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        DessertsRepository repository = DessertsRepository.getInstance();
        getSupportFragmentManager().setFragmentFactory(new MyFragmentFactory(repository));
        super.onCreate(savedInstanceState);
    }
}

Etkinlikteki FragmentFactory değerinin ayarlanması, parçayı geçersiz kılar her şeyi öğretecek. Başka bir deyişle, eklediğiniz alt parçaların childFragmentManager öğesi, özel parçası fabrika ayarlarına ayarlanır.

FragmentFactory ile test et

Tek etkinlik mimarisinde, parçalarınızı yalıtım oluşturmak için FragmentScenario sınıfını kullanır. Uygulamanızın özel onCreate mantığına güvenmeyeceğiniz için etkinliği varsa FragmentFactory öğesini bağımsız değişken olarak şu örnekte gösterildiği gibi parça testinize ekleyin:

// Inside your test
val dessertRepository = mock(DessertsRepository::class.java)
launchFragment<DessertsFragment>(factory = MyFragmentFactory(dessertRepository)).onFragment {
    // Test Fragment logic
}

Bu test süreci hakkında ayrıntılı bilgi ve tam örnekler için Parçalarınızı test etme konusuna bakın.