Gezinme bileşeniyle programatik olarak etkileşim kurun

Gezinme bileşeni, bunları programatik olarak oluşturma ve etkileşime geçirme satır içi metin ekleyin.

NavHostFragment oluşturma

Tekliflerinizi otomatikleştirmek ve optimize etmek için NavHostFragment.create() belirli bir grafik kaynağıyla programatik olarak bir NavHostFragment oluşturmak için aşağıdaki örnekte gösterildiği gibi:

Kotlin

val finalHost = NavHostFragment.create(R.navigation.example_graph)
supportFragmentManager.beginTransaction()
    .replace(R.id.nav_host, finalHost)
    .setPrimaryNavigationFragment(finalHost) // equivalent to app:defaultNavHost="true"
    .commit()

Java

NavHostFragment finalHost = NavHostFragment.create(R.navigation.example_graph);
getSupportFragmentManager().beginTransaction()
    .replace(R.id.nav_host, finalHost)
    .setPrimaryNavigationFragment(finalHost) // equivalent to app:defaultNavHost="true"
    .commit();

setPrimaryNavigationFragment(finalHost) ile NavHost izin verildiğini unutmayın müdahale sisteminin Geri düğmesine bastığında. Bu davranışı Google Analytics 4'te de app:defaultNavHost="true" ekleyerek NavHost XML. Yaklaşımınızı özel Geri düğmesi davranışı ve NavHost geri düğmesine basılmasını istemiyorsanız null - setPrimaryNavigationFragment().

Gezinme 2.2.0'dan başlayarak, istediğiniz zaman NavBackStackEntry öğesini çağırarak gezinme yığınındaki herhangi bir hedefe NavController.getBackStackEntry(), hedef kimliği iletir. Arka yığın birden fazla örnek içeriyorsa belirtilen hedefin getBackStackEntry() işlevi, en üstteki örneği döndürür seçeceğim.

Döndürülen NavBackStackEntry, bir Lifecycle, bir ViewModelStore ve bir SavedStateRegistry teşvik edebilirsiniz. Bu nesneler, arka yığındaki hedefin ömrü boyunca geçerlidir. İlişkili hedef otomatik olarak Lifecycle kaldırılır, durum kaydedilmez ve ViewModel nesneleri temizlenir.

Bu mülkler size bir Lifecycle ve ViewModel nesne için bir mağaza sağlar ve Çevik yaklaşımla kayıtlı duruma bakılmaksızın kullandığınız hedef türünden emin olmanız gerekir. Bu, özellikle paydaşlarla çalışırken otomatik olarak ilişkilendirilmiş Lifecycle bulunmayan hedef türleri (ör. özel hedefler)

Örneğin, NavBackStackEntry öğesinin Lifecycle değerini bir parçanın veya etkinliğin Lifecycle öğesini gözlemlersiniz. Ayrıca, NavBackStackEntry bir LifecycleOwner değeridir, yani şu durumlarda kullanabilirsiniz: aşağıdaki örnekteki gibi LiveData veya yaşam döngüsüne duyarlı diğer bileşenlerle şu örneği inceleyin:

Kotlin

myViewModel.liveData.observe(backStackEntry, Observer { myData ->
    // react to live data update
})

Java

myViewModel.getLiveData().observe(backStackEntry, myData -> {
    // react to live data update
});

Yaşam döngüsü durumu, navigate() öğesini her çağırdığınızda otomatik olarak güncellenir. Arka yığının en üstünde olmayan hedeflerin yaşam döngüsü durumları Hedefler hala altında görünür durumdaysa RESUMED - STARTED arasında FloatingWindow hedefi (ör. iletişim kutusu hedefi veya STOPPED) aksi takdirde.

Bir sonucu önceki Hedefe döndürme

Gezinme 2.3 ve sonraki sürümlerde NavBackStackEntry, SavedStateHandle SavedStateHandle, verileri depolamak ve almak için kullanılabilen bir anahtar/değer eşlemesidir dışı verilerdir. Bu değerler, yapılandırma dahil olmak üzere işlem ölümü yoluyla korunur. ve aynı nesne üzerinden erişilebilir durumda kalmasını sağlar. Verilen SavedStateHandle, verilere erişebilir ve hedefler arasında veri aktarabilirsiniz. Bu, özellikle bir kullanıcıdan gelen verileri geri alma mekanizması olarak başka bir hedef belirleyebilirsiniz.

Verileri Hedef B'den Hedef A'ya geri aktarmak için önce sonucu SavedStateHandle cihazında dinlemek için Hedef A'yı ayarlayın. Bunu yapmak için şunu kullanarak NavBackStackEntry öğesini alın: getCurrentBackStackEntry() API ve ardından observe LiveData sağlayan: SavedStateHandle.

Kotlin

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    val navController = findNavController();
    // We use a String here, but any type that can be put in a Bundle is supported
    navController.currentBackStackEntry?.savedStateHandle?.getLiveData<String>("key")?.observe(
        viewLifecycleOwner) { result ->
        // Do something with the result.
    }
}

Java

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    NavController navController = NavHostFragment.findNavController(this);
    // We use a String here, but any type that can be put in a Bundle is supported
    MutableLiveData<String> liveData = navController.getCurrentBackStackEntry()
            .getSavedStateHandle()
            .getLiveData("key");
    liveData.observe(getViewLifecycleOwner(), new Observer<String>() {
        @Override
        public void onChanged(String s) {
            // Do something with the result.
        }
    });
}

Hedef B'de sonucu şunun SavedStateHandle: set getPreviousBackStackEntry() API'yi kullanarak A Hedefi.

Kotlin

navController.previousBackStackEntry?.savedStateHandle?.set("key", result)

Java

navController.getPreviousBackStackEntry().getSavedStateHandle().set("key", result);

Bir sonucu yalnızca bir kez işlemek isterseniz remove() SavedStateHandle düğmesine basın. Etiketteki LiveData, son sonucu herhangi bir sonuca döndürmeye devam eder yeni Observer örneği.

İletişim kutusu hedeflerini kullanırken dikkat edilmesi gereken noktalar

Tam görünümünü alan bir hedefe navigate gittiğinizde NavHost (<fragment> hedefi gibi), önceki hedef yaşam döngüsü durduğu için LiveData sağlayan: SavedStateHandle.

Ancak bir iletişim kutusu hedefi, ekranda da görünür ve böylece Şu anki hedef olmamasına rağmen STARTED. Bu, paydaşlara Aşağıdaki gibi yaşam döngüsü yöntemlerinden getCurrentBackStackEntry() onViewCreated(), iletişim kutusu hedefinin NavBackStackEntry değerini döndürür veya yapılandırma değişikliğinden ya da ölüm ve yeniden oluşturma işlemlerinden sonra (iletişim kutusu diğer hedefin üzerine geri yüklenir). Bu nedenle getBackStackEntry() Her zaman doğru NavBackStackEntry.

Bu aynı zamanda, LiveData sonucu için ayarladığınız tüm Observer iletişim kutusu hedefleri ekrandayken bile tetiklenir. Şu durumda: yalnızca iletişim kutusu hedefi kapatıldığında ve yeni iletişim kutusu seçildiğinde temel hedef mevcut hedef haline gelirse, Lifecycle, NavBackStackEntry ile ilişkilendirilir ve sonucu alır yalnızca RESUMED olduğunda.

Kotlin

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    val navController = findNavController();
    // After a configuration change or process death, the currentBackStackEntry
    // points to the dialog destination, so you must use getBackStackEntry()
    // with the specific ID of your destination to ensure we always
    // get the right NavBackStackEntry
    val navBackStackEntry = navController.getBackStackEntry(R.id.your_fragment)

    // Create our observer and add it to the NavBackStackEntry's lifecycle
    val observer = LifecycleEventObserver { _, event ->
        if (event == Lifecycle.Event.ON_RESUME
            && navBackStackEntry.savedStateHandle.contains("key")) {
            val result = navBackStackEntry.savedStateHandle.get<String>("key");
            // Do something with the result
        }
    }
    navBackStackEntry.lifecycle.addObserver(observer)

    // As addObserver() does not automatically remove the observer, we
    // call removeObserver() manually when the view lifecycle is destroyed
    viewLifecycleOwner.lifecycle.addObserver(LifecycleEventObserver { _, event ->
        if (event == Lifecycle.Event.ON_DESTROY) {
            navBackStackEntry.lifecycle.removeObserver(observer)
        }
    })
}

Java

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    NavController navController = NavHostFragment.findNavController(this);
    // After a configuration change or process death, the currentBackStackEntry
    // points to the dialog destination, so you must use getBackStackEntry()
    // with the specific ID of your destination to ensure we always
    // get the right NavBackStackEntry
    final NavBackStackEntry navBackStackEntry = navController.getBackStackEntry(R.id.your_fragment);

    // Create our observer and add it to the NavBackStackEntry's lifecycle
    final LifecycleEventObserver observer = new LifecycleEventObserver() {
        @Override
        public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
            if (event.equals(Lifecycle.Event.ON_RESUME)
                && navBackStackEntry.getSavedStateHandle().contains("key")) {
                String result = navBackStackEntry.getSavedStateHandle().get("key");
                // Do something with the result
            }
        }
    };
    navBackStackEntry.getLifecycle().addObserver(observer);

    // As addObserver() does not automatically remove the observer, we
    // call removeObserver() manually when the view lifecycle is destroyed
    getViewLifecycleOwner().getLifecycle().addObserver(new LifecycleEventObserver() {
        @Override
        public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
            if (event.equals(Lifecycle.Event.ON_DESTROY)) {
                navBackStackEntry.getLifecycle().removeObserver(observer)
            }
        }
    });
}

Gezinme geri yığını, NavBackStackEntry Yalnızca her bir hedef için değil, aynı zamanda her üst gezinme için tek bir hedefi içeren grafiktir. Bu işlem, Gezinme grafiğine dahil edilen NavBackStackEntry. Gezinme grafik kapsamlı NavBackStackEntry, aşağıdaki gibi görünen ViewModel için kullanıcı arayüzüyle ilgili verileri Google Haritalar ve Google Earth arasındaki hedefler. Bu şekilde oluşturulan tüm ViewModel nesneleri ilişkilendirilmiş NavHost ve ViewModelStore öğeleri temizlenir veya gezinme grafiği arka yığından atılır.

Aşağıdaki örnekte,ViewModel gezinme grafiği:

Kotlin

val viewModel: MyViewModel
        by navGraphViewModels(R.id.my_graph)

Java

NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.my_graph);
MyViewModel viewModel = new ViewModelProvider(backStackEntry).get(MyViewModel.class);

Navigasyon 2.2.0 veya daha eski bir sürümü kullanıyorsanız kendi fabrika ayarı ViewModels ile Kayıtlı Durum, aşağıdaki örnekte gösterildiği gibi:

Kotlin

val viewModel: MyViewModel by navGraphViewModels(R.id.my_graph) {
    SavedStateViewModelFactory(requireActivity().application, requireParentFragment())
}

Java

NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.my_graph);

ViewModelProvider viewModelProvider = new ViewModelProvider(
        backStackEntry.getViewModelStore(),
        new SavedStateViewModelFactory(
                requireActivity().getApplication(), requireParentFragment()));

MyViewModel myViewModel = provider.get(myViewModel.getClass());

ViewModel hakkında daha fazla bilgi için bkz. ViewModel'e Genel Bakış.

Şişmiş gezinme grafiklerini değiştirme

Şişmiş bir gezinme grafiğini çalışma zamanında dinamik olarak değiştirebilirsiniz.

Örneğin, BottomNavigationView web sitesinin varsayılan hedefi olan NavGraph öğesine bağlı NavGraph, uygulama başlatılırken seçilen sekmeyi belirtir. Ancak, gerektiğinde bu davranışı geçersiz kılmanız gerekir (örneğin, bir kullanıcı tercihinin, Uygulama başlangıcında yüklenmesi tercih edilen bir sekme olmalıdır. Alternatif olarak uygulamanız kullanıcı davranışına dayalı olarak başlangıç sekmesini değiştirmesi gerektiğini unutmayın. Şunları yapabilirsiniz: bu durumlarda, sitenin varsayılan hedefini dinamik olarak NavGraph.

Bu NavGraph türünü düşünün:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_graph"
    app:startDestination="@id/home">
    <fragment
        android:id="@+id/home"
        android:name="com.example.android.navigation.HomeFragment"
        android:label="fragment_home"
        tools:layout="@layout/fragment_home" />
    <fragment
        android:id="@+id/location"
        android:name="com.example.android.navigation.LocationFragment"
        android:label="fragment_location"
        tools:layout="@layout/fragment_location" />
    <fragment
        android:id="@+id/shop"
        android:name="com.example.android.navigation.ShopFragment"
        android:label="fragment_shop"
        tools:layout="@layout/fragment_shop" />
    <fragment
        android:id="@+id/settings"
        android:name="com.example.android.navigation.SettingsFragment"
        android:label="fragment_settings"
        tools:layout="@layout/fragment_settings" />
</navigation>

Bu grafik yüklendiğinde app:startDestination özelliği, HomeFragment tarihinin görüntülenmesine. Başlangıç hedefini geçersiz kılmak için dinamik olarak şunları yapın:

  1. İlk olarak, NavGraph değerini manuel olarak şişirin.
  2. Başlangıç hedefini geçersiz kılın.
  3. Son olarak, grafiği NavController öğesine manuel olarak ekleyin.

Kotlin

val navHostFragment =
        supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment

val navController = navHostFragment.navController
val navGraph = navController.navInflater.inflate(R.navigation.bottom_nav_graph)
navGraph.startDestination = R.id.shop
navController.graph = navGraph
binding.bottomNavView.setupWithNavController(navController)

Java

NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager()
        .findFragmentById(R.id.nav_host_fragment);

NavController navController = navHostFragment.getNavController();
NavGraph navGraph = navController.getNavInflater().inflate(R.navigation.bottom_nav_graph);
navGraph.setStartDestination(R.id.shop);
navController.setGraph(navGraph);
NavigationUI.setupWithNavController(binding.bottomNavView, navController);

Artık uygulamanız başlatıldığında HomeFragment yerine ShopFragment gösterilir.

Derin bağlantılar kullanılırken NavController, bir arka yığın oluşturur otomatik olarak oluşturulur. Kullanıcı gittiğinde derin bağlantıya gider ve geri giderse bir noktada başlar. Başlangıç hedefini tekniği kullanarak, doğru başlangıcı oluşturulan arka yığınına eklenir.

Bu tekniğin, aynı zamanda ekibinizin bir parçası olan diğer unsurların da geçersiz kılınmasına NavGraph değerini gerektiği gibi değiştirin. Grafikte tüm değişikliklerin yapılması gerekir önceki önce setGraph() Derin bağlantılar işlenirken, durumu geri yüklerken ve başa dönerken kullanılır hedefi belirir.