具有多个堆栈的Android JetPack导航 [英] Android JetPack navigation with multiple stack

本文介绍了具有多个堆栈的Android JetPack导航的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在底部导航中使用Jetpack导航version 1.0.0-alpha04.它可以工作,但导航无法正确进行.例如,如果我有选项卡A和选项卡B,然后从选项卡AI转到页面C,然后从那里转到选项卡B,然后再次返回到选项卡A,我将在选项卡A中看到根片段,而在页面C中看不到根片段不是我所期望的.

我正在寻找一种解决方案,以使每个选项卡具有不同的堆栈,因此当我返回到每个选项卡时,每个选项卡的状态都将保留,而且我也不喜欢将所有这些片段都保留在内存中,因为它的性能很差.对性能的影响,在jetpack导航之前,我使用了这个库 https://github.com/ncapdevi/FragNav,那确实是做什么的,现在我在寻找与Jetpack导航相同的东西.

I'm using Jetpack Navigation version 1.0.0-alpha04 with bottom navigation. It works but the navigation doesn't happen correctly. For example, if I have tab A and tab B and from tab A I go to Page C and from there I go to tab B and come back to tab A again, I will see root fragment in the tab A and not page C which does not what I expect.

I'm looking for a solution to have a different stack for each tab, so the state of each tab is reserved when I come back to it, Also I don't like to keep all this fragment in the memory since it has a bad effect on performance, Before jetpack navigation, I used this library https://github.com/ncapdevi/FragNav, That does exactly what, Now I'm looking for the same thing with jetpack navigation.

推荐答案

尽管仍然没有一流的支持(在撰写本文时),但Google现在通过示例更新了其示例.他们认为现在应该如何解决: https://github.com/googlesamples/android-architecture-components/tree/master/NavigationAdvancedSample

EDIT 2: Though still no first class support (as of writing this), Google has now updated their samples with an example of how they think this should be solved for now: https://github.com/googlesamples/android-architecture-components/tree/master/NavigationAdvancedSample

主要原因是您仅使用一个NavHostFragment来容纳应用程序的整个后盖.

The major reason is you only use one NavHostFragment to hold the whole back stack of the app.

解决方案是每个选项卡都应拥有自己的后退堆栈.

The solution is that each tab should hold its own back stack.

  • 在主布局中,每个标签片段都用FrameLayout包裹.
  • 每个选项卡片段都是NavHostFragment,并包含其自己的导航图,以使每个选项卡片段都具有自己的后向堆栈.
  • BottomNavigtionView中添加BottomNavigationView.OnNavigationItemSelectedListener以处理每个FrameLayout的可见性.
  • In your main layout, wrap each tab fragment with a FrameLayout.
  • Each tab fragment is a NavHostFragment and contains its own navigation graph in order to make each tab fragment having its own back stack.
  • Add a BottomNavigationView.OnNavigationItemSelectedListener to BottomNavigtionView to handle the visibility of each FrameLayout.

这也可以解决您的"...我不希望将所有这些片段都保留在内存中...",因为默认情况下,使用NavHostFragment进行导航时会使用fragmentTransaction.replace(),即您将始终只有与NavHostFragment一样多的片段.其余的只是在导航图的后堆栈中.

This also takes care of your "...I don't like to keep all this fragment in memory...", because a Navigation with NavHostFragment by default uses fragmentTransaction.replace(), i.e. you will always only have as many fragments as you have NavHostFragments. The rest is just in the back stack of your navigation graph.

修改:Google正在开发本机实现 https://issuetracker.google.com/issues/80029773#comment25

Google is working on a native implementation https://issuetracker.google.com/issues/80029773#comment25

更多详细信息

假设您有一个BottomNavigationView,其中有两个菜单选项DogsCats.

Let's say you have a BottomNavigationView with 2 menu choices, Dogs and Cats.

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/dogMenu"
        .../>

    <item android:id="@+id/catMenu"
        .../>
</menu>

然后您需要2个导航图,例如dog_navigation_graph.xmlcat_navigation_graph.xml.

Then you need 2 navigation graphs, say dog_navigation_graph.xml and cat_navigation_graph.xml.

dog_navigation_graph可能看起来像

<navigation
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/dog_navigation_graph"
    app:startDestination="@id/dogMenu">
</navigation>

以及对应的cat_navigation_graph.

在您的activity_main.xml中,添加2个NavHostFragment s

In your activity_main.xml, add 2 NavHostFragments

<FrameLayout
    android:id="@+id/frame_dog"
    ...>

    <fragment
        android:id="@+id/dog_navigation_host_fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="androidx.navigation.fragment.NavHostFragment"
        app:navGraph="@navigation/dog_navigation_graph"
        app:defaultNavHost="true"/>
</FrameLayout>

,然后在下面添加与您的猫NavHostFragment相对应的内容.在您的Cat框架布局上,设置android:visibility="invisible"

and underneath add the corresponding for your cat NavHostFragment. On your cat frame layout, set android:visibility="invisible"

现在,您可以在MainActivityonCreateView

bottom_navigation_view.setOnNavigationItemSelectedListener { item ->
    when (item.itemId) {
        R.id.dogMenu -> showHostView(host = 0)
        R.id.catMenu -> showHostView(host = 1)
    }
    return@setOnNavigationItemSelectedListener true
}

showHostView()的全部工作是切换包裹NavHostFragmentFrameLayout的可见性.因此,请确保以某种方式保存它们,例如在onCreateView

All that showHostView() is doing is toggling the visibility of your FrameLayouts that are wrapping the NavHostFragments. So make sure to save them in some way, e.g. in onCreateView

val hostViews = arrayListOf<FrameLayout>()  // Member variable of MainActivity
hostViews.apply {
    add(findViewById(R.id.frame_dog))
    add(findViewById(R.id.frame_cat))
}

现在很容易切换哪个hostViews应该是可见的还是不可见的.

Now it's easy to toggle which hostViews should be visible and invisible.

这篇关于具有多个堆栈的Android JetPack导航的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆