FragmentManager
, uygulamanızın parçaları üzerinde bunları ekleme, çıkarma veya değiştirme ve arka yığına ekleme gibi işlemler yapmaktan sorumlu sınıftır.
Jetpack Navigation kitaplığını kullanıyorsanız FragmentManager
ile doğrudan etkileşimde bulunamazsınız. Bu kitaplık sizin adınıza FragmentManager
ile çalışır. Ancak, parça kullanan tüm uygulamalar belirli bir düzeyde FragmentManager
kullanır. Bu nedenle, parçanın ne olduğunu ve nasıl çalıştığını anlamak önemlidir.
Bu sayfada ele alınan konular:
FragmentManager
platformuna nasıl erişilir?- Etkinlikleriniz ve parçalarınızla ilişkili olarak
FragmentManager
rolü. - Arka yığını
FragmentManager
ile yönetme. - Parçalarınıza veri ve bağımlılıkları sağlama.
FragmentManager'a erişme
FragmentManager
öğesine bir etkinlikten veya parçadan erişebilirsiniz.
FragmentActivity
ve AppCompatActivity
gibi alt sınıfları, FragmentManager
'a getSupportFragmentManager()
yöntemiyle erişebilir.
Parçalar, bir veya daha fazla alt parçayı barındırabilir. Bir parçanın içinde, parçanın alt öğelerini getChildFragmentManager()
aracılığıyla yöneten FragmentManager
referansı alabilirsiniz.
FragmentManager
ana makinesine erişmeniz gerekiyorsa getParentFragmentManager()
kullanabilirsiniz.
Parçalar, bunların ana makineleri ve her biriyle ilişkilendirilmiş FragmentManager
örnekleri arasındaki ilişkileri görmek için birkaç örneği burada bulabilirsiniz.
Şekil 1'de, her biri tek bir etkinlik ana makinesine sahip iki örnek gösterilmektedir. Bu örneklerin her ikisindeki ana makine etkinliği, kullanıcıya üst düzey gezinmeyi bir BottomNavigationView
olarak gösterir. Bu öğe, uygulamadaki ana makine parçasını farklı ekranlarla değiştirmekten sorumludur. Her ekran ayrı bir parça olarak uygulanır.
Örnek 1'deki ana makine parçası, bölünmüş görünüm ekranını oluşturan iki alt parça barındırır. Örnek 2'deki ana makine parçası, kaydırma görünümünün görünen parçasını oluşturan tek bir alt parçayı barındırır.
Bu kuruluma göre, her bir ana makineyi, alt parçalarını yöneten bir FragmentManager
öğesine sahip olarak düşünebilirsiniz. Bu, Şekil 2'de supportFragmentManager
, parentFragmentManager
ve childFragmentManager
arasındaki mülk eşlemeleriyle birlikte gösterilmiştir.
Referansta bulunulacak uygun FragmentManager
özelliği, çağrı sitesinin parça hiyerarşisinde nerede bulunduğuna ve erişmeye çalıştığınız parça yöneticisine bağlıdır.
FragmentManager
için referansınız olduğunda, bunu kullanıcıya gösterilen parçaları değiştirmek için kullanabilirsiniz.
Alt parçalar
Genel olarak, uygulamanız uygulama projenizde bir veya az sayıda etkinlikten oluşur ve her etkinlik bir grup ilgili ekranı temsil eder. Etkinlik, üst düzey gezinmenin yerleştirileceği bir nokta ve parçalar arasındaki ViewModel
nesnelerinin ve diğer görünüm durumlarının kapsamının belirlenmesi için bir yer sağlayabilir. Parça, uygulamanızdaki ayrı bir hedefi temsil eder.
Bölünmüş görünümde veya kontrol panelinde olduğu gibi, aynı anda birden fazla parça göstermek istiyorsanız hedef parçanız ve alt parça yöneticisi tarafından yönetilen alt parçaları kullanabilirsiniz.
Alt parçalar için diğer kullanım alanları şunlardır:
- Bir dizi alt parça görünümünü yönetmek için üst parçada
ViewPager2
kullanarak bir ekran slaytları. - Bir dizi ilgili ekranda alt gezinme.
- Jetpack Navigasyon, alt parçaları ayrı hedefler olarak kullanır. Bir etkinlik tek bir üst öğe
NavHostFragment
barındırır ve kullanıcılar uygulamanızda gezinirken bu alanın alanını farklı alt hedef parçalarla doldurur.
FragmentManager'ı kullanma
FragmentManager
, parça arka yığınını yönetir. Çalışma zamanında FragmentManager
, kullanıcı etkileşimlerine yanıt olarak parçaları ekleme veya kaldırma gibi arka yığın işlemleri gerçekleştirebilir. Her değişiklik grubu, FragmentTransaction
adı verilen tek bir birim olarak birlikte işlenir.
Parça işlemleri hakkında daha ayrıntılı bir tartışma için parça işlemleri kılavuzunu inceleyin.
Kullanıcı, cihazındaki Geri düğmesine dokunduğunda veya FragmentManager.popBackStack()
çağrısını yaptığınızda, en üstteki parça işlemi yığından çıkar. Yığında başka parça işlemi yoksa ve alt parçalar kullanmıyorsanız Geri etkinliği, etkinliği baloncuk olarak gösterir. Alt parçalar kullanıyorsanız alt ve kardeş parçalar için özel noktalara bakın.
Bir işlemde addToBackStack()
çağrısı yaptığınızda, işlem birden fazla parça ekleme veya birden fazla container'daki parçaları değiştirme gibi herhangi bir sayıda işlemi içerebilir.
Geri yığın patlatıldığında, tüm bu işlemler tek bir atomik işlem olarak tersine çevrilir. Ancak popBackStack()
çağrısından önce ek işlemler yaptıysanız ve işlem için addToBackStack()
kullanmadıysanız bu işlemler geri alınmaz. Bu nedenle, arka yığını etkileyen işlemleri tek bir FragmentTransaction
içinde etkilemeyen işlemlerle karıştırmaktan kaçının.
İşlem gerçekleştirme
Düzen kapsayıcısındaki bir parçayı görüntülemek için FragmentManager
kullanarak FragmentTransaction
oluşturun. Ardından işlem sırasında kapsayıcıda bir add()
veya replace()
işlemi gerçekleştirebilirsiniz.
Örneğin, basit bir FragmentTransaction
aşağıdaki gibi 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
, şu anda R.id.fragment_container
kimliğiyle tanımlanan düzen kapsayıcısında bulunan parçayı (varsa) değiştirir. Parça sınıfının replace()
yöntemine sağlanması, FragmentManager
ürününün, FragmentFactory
yöntemini kullanarak örneklendirmeyi işleyebilmesini sağlar.
Daha fazla bilgi için Parçalarınıza bağımlılıkları sağlama bölümüne bakın.
setReorderingAllowed(true)
, animasyonların ve geçişlerin düzgün çalışması için işlemle ilgili parçaların durum değişikliklerini optimize eder. Animasyonlar ve geçişlerle gezinme hakkında daha fazla bilgi için Parça işlemleri ve Animasyonları kullanarak parçalar arasında gezinme bölümlerine bakın.
addToBackStack()
çağrıldığında işlem arka yığına kaydedilir. Kullanıcı, daha sonra Geri düğmesine dokunarak işlemi tersine çevirebilir ve önceki parçayı geri getirebilir. Tek bir işleme birden fazla parça ekler veya kaldırırsanız arka yığın açıldığında tüm bu işlemler geri alınır. addToBackStack()
çağrısında sağlanan isteğe bağlı ad, popBackStack()
kullanarak belirli bir işleme geri dönme olanağı sağlar.
Bir parçayı kaldıran bir işlem gerçekleştirirken addToBackStack()
yöntemini çağırmazsanız işlem gerçekleştiğinde kaldırılan parça kaldırılır ve kullanıcı geri gidemez. Bir parçayı kaldırırken addToBackStack()
çağrısı yaparsanız parça yalnızca STOPPED
olur ve kullanıcı geri döndüğünde daha sonra RESUMED
olur. Bu durumda görünümü kaldırılır. Daha fazla bilgi için Parça yaşam döngüsü bölümüne bakın.
Mevcut bir parçayı bulma
findFragmentById()
kullanarak bir düzen kapsayıcısındaki mevcut parçaya referans alabilirsiniz.
Bir parçayı XML'den şişirilmişken verilen kimliğe ya da FragmentTransaction
içine eklendiğinde kapsayıcı kimliğine göre aramak için findFragmentById()
kullanın. 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 findFragmentByTag()
kullanarak bir referans alabilirsiniz.
Düzeniniz içinde veya FragmentTransaction
içindeki bir add()
ya da replace()
işlemi sırasında tanımlanan parçalarda android:tag
XML özelliğini kullanarak etiket atayabilirsiniz.
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
Herhangi bir zamanda parça arka yığınını yalnızca bir FragmentManager
kontrol edebilir. Uygulamanız ekranda aynı anda birden fazla eşdüzey parça gösteriyorsa veya uygulamanız alt parçalar kullanıyorsa uygulamanızın birincil gezinmesini işlemek için bir FragmentManager
atanır.
Bir parça işleminin birincil gezinme parçasını tanımlamak için işlemde setPrimaryNavigationFragment()
yöntemini çağırın ve childFragmentManager
birincil kontrole sahip parçanın örneğini iletin.
Gezinme yapısını bir dizi katman olarak düşünebilirsiniz. Bu katmandaki etkinlik, en dıştaki katman olarak kabul edilir ve altındaki alt parçalardan oluşan her katman sarmalanır. Her katmanın tek bir birincil gezinme parçası vardır.
Geri etkinliği gerçekleştiğinde, en içteki katman gezinme davranışını kontrol eder. En içteki katmanda geri oluşturulacak parça işlemi kalmadığında, kontrol bir sonraki katmana geri döner ve bu işlem siz etkinliğe ulaşana kadar tekrarlanır.
İki veya daha fazla parça aynı anda görüntülendiğinde bunlardan yalnızca biri birincil gezinme parçası olur. Bir parçanın birincil gezinme parçası olarak ayarlanması, önceki parçanın tanımlamasını kaldırır. Önceki örneği kullanarak ayrıntı parçasını birincil gezinme parçası olarak ayarlarsanız ana parçanın ataması kaldırılır.
Birden fazla arka sırayı destekleme
Bazı durumlarda, uygulamanızın birden fazla arka yığını desteklemesi gerekebilir. Uygulamanızın alt gezinme çubuğu kullanması, bunun yaygın bir örneğidir. FragmentManager
, saveBackStack()
ve restoreBackStack()
yöntemleriyle birden fazla arka yığını desteklemenize olanak tanır. Bu yöntemler, bir arka yığını kaydedip farklı bir arka yığını geri yükleyerek arka yığınlar arasında geçiş yapmanızı sağlar.
saveBackStack()
, isteğe bağlı name
parametresiyle popBackStack()
çağrısına benzer şekilde çalışır: Belirtilen işlem ve yığında ondan sonraki tüm işlemler başlatılır. Aralarındaki fark, saveBackStack()
özelliğinin pop-up işlemlerdeki tüm parçaların durumunu kaydetmesidir.
Örneğin, daha önce aşağıdaki örnekte gösterildiği gibi addToBackStack()
kullanarak bir FragmentTransaction
işlemi yaparak arka yığına daha önce bir parça eklediğinizi varsayalım:
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, saveBackStack()
yöntemini çağırarak bu parça işlemini ve ExampleFragment
durumunu kaydedebilirsiniz:
Kotlin
supportFragmentManager.saveBackStack("replacement")
Java
supportFragmentManager.saveBackStack("replacement");
Başlatılan işlemlerin ve kayıtlı tüm parça durumlarının geri yüklenmesini sağlamak için restoreBackStack()
öğesini aynı ad parametresiyle çağırabilirsiniz:
Kotlin
supportFragmentManager.restoreBackStack("replacement")
Java
supportFragmentManager.restoreBackStack("replacement");
Parçalarınıza bağımlılıklar sağlama
Bir parça eklerken, parçayı manuel olarak örnekleyebilir ve FragmentTransaction
öğesine ekleyebilirsiniz.
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, oluşturduğunuz parçanın örneği, kullanılan örnek olur. Ancak yapılandırma değişikliği sırasında etkinliğiniz ve tüm parçalarınız yok edilir ve ardından en geçerli Android kaynaklarıyla yeniden oluşturulur.
FragmentManager
tüm bunları sizin için halleder: Parçalarınızın örneklerini yeniden oluşturur, bunları ana makineye ekler ve arka yığın durumunu yeniden oluşturur.
Varsayılan olarak FragmentManager
, çerçevenin parçanızın yeni bir örneğini örneklendirmek için sağladığı bir FragmentFactory
kullanır. Bu varsayılan fabrika, parçanız için bağımsız değişkensiz oluşturucu bulmak ve çağırmak üzere yansımayı kullanır. Bu, parçanıza bağımlılıklar sağlamak için bu varsayılan fabrikayı kullanamayacağınız anlamına gelir. Aynı zamanda, parçanızı ilk kez oluşturmak için kullandığınız herhangi bir özel oluşturucunun, yeniden oluşturma sırasında varsayılan olarak kullanılmayacağı anlamına gelir.
Parçanıza bağımlılıklar sağlamak veya herhangi bir özel oluşturucu kullanmak için özel bir FragmentFactory
alt sınıfı oluşturup FragmentFactory.instantiate
değerini geçersiz kılın.
Daha sonra, FragmentManager
öğesinin varsayılan fabrikasını özel fabrikanızla geçersiz kılabilirsiniz. Bu ayar daha sonra parçalarınızı göstermek için kullanılır.
Bulunduğunuz şehirde popüler tatlıları görüntülemekten sorumlu bir DessertsFragment
sahibi olduğunuzu ve DessertsFragment
adlı iş ortağının, kullanıcınıza doğru kullanıcı arayüzünü göstermesi için gereken bilgileri sağlayan bir DessertsRepository
sınıfına bağımlılığı olduğunu varsayalım.
DessertsFragment
öğenizi, oluşturucuda DessertsRepository
örneği gerektirecek şekilde tanımlayabilirsiniz.
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. ... }
Basit bir FragmentFactory
uygulaması aşağıdakine benzer görünebilir.
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 FragmentFactory
alt sınıfları seçilidir ve DessertsFragment
için özel parça oluşturma mantığı sağlamak amacıyla instantiate()
yöntemini geçersiz kılar.
Diğer parça sınıfları, FragmentFactory
ile super.instantiate()
arasındaki varsayılan davranışa göre işlenir.
Daha sonra, FragmentManager
üzerinde bir özellik ayarlayarak MyFragmentFactory
uygulamasını, uygulamanızın parçalarını oluştururken kullanılacak fabrika olarak tanımlayabilirsiniz. Parçalarınızı yeniden oluştururken MyFragmentFactory
kullanıldığından emin olmak için bu özelliği etkinliğinizin super.onCreate()
özelliğinden önce ayarlamanız gerekir.
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); } }
Etkinlikte FragmentFactory
ayarlanırsa etkinliğin parça hiyerarşisinde parça oluşturmayı geçersiz kılar. Başka bir deyişle, eklediğiniz alt parçaların childFragmentManager
değeri, daha düşük bir düzeyde geçersiz kılınmadığı sürece burada ayarlanan özel parça fabrikasını kullanır.
FragmentFactory ile test edin
Tek etkinlik mimarisinde, FragmentScenario
sınıfını kullanarak parçalarınızı ayrı ayrı test edin. Etkinliğinizin özel onCreate
mantığını kullanamayacağınız için, aşağıdaki örnekte gösterildiği gibi, FragmentFactory
öğesini parça testinize bağımsız değişken olarak aktarabilirsiniz:
// 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 örneklerin tamamı için Parçalarınızı test etme bölümüne bakın.