除了寻找解决方案之外,我还想了解我是否弄错了(在这种情况下,我肯定会需要解决方案),请耐心等待。
(TL; DR?->转到#使用缓存的视图)
我正在使用Android的JetPack组件,主要是LiveData
和Navigation
。在发布时,我使用的是最新的并且被认为是稳定的(或者我希望如此):
由于我必须使用BottomNavigationView
并且默认行为(与Navigation
一起使用)是不断重新创建片段,因此丢失了任何特定于选项卡的导航进度,我找到了一个解决方案Google Issue (#80029773)使用NavigationExtensions.kt
(link)。
由于我在Kotlin并不懂书,而且没有涉及太多细节,最近我改写了NavigationExtensions.kt
,因为我获得了更多有关碎片如何工作以及经理如何工作的知识。
我觉得使用Kotlin扩展程序是技术上的债务,我有一天必须摆脱掉。
但是因为我不得不重写它,所以我想到了一个简单的解决方案:为什么不使用嵌套片段来处理嵌套导航,BottomNavigationView
中每个选项卡一个?
这就是我所做的。我创建了一个带有两个参数的NestedNavigationFragment
:
ARG_NAVIGATION_GRAPH_ID
,用于关联所选标签的嵌套导航图ID; ARG_NAVIGATION_GRAPH_ARGS
,是所述嵌套导航图的startDestination
所需的可选参数。非常简单。每个标签一个导航图。
它的布局也很简单:
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:clickable="true"
android:focusable="true"
tools:contex="com.mycompany.custom.navigation.NestedNavigationFragment">
<fragment
android:id="@+id/nav_host_fragment"
android:tag="@string/nested_navigation_fragment_nav_host_fragment_tag"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true" />
</FrameLayout>
</layout>
使用最近与OnBackPressedDispatcher
一起使用的app:defaultNavHost="true"
,我对导航有很好的控制。
然后,您将看到,NavHostFragment
将使用NestedNavigationFragment
的子FragmentManager 来显示使用嵌套(子)片段的嵌套导航。
在接下来的事情中记住这一点非常重要。
我说我改写了NavigationExtensions.kt
。无需显示代码,就像下面这样简单。
选择标签后,一个FragmentTransaction
将...
Fragment
附加关联的FragmentManager#findFragmentByTag
(如果存在)或创建一个新实例,并将其添加到相同的backstack
(相同的堆栈字符串名称)中; FragmentManager#findFragmentByTag
的同时使用FragmentManager#getFragments
来分离任何先前添加/附加的片段; 就是这样。
我们去了,我们终于明白了。到目前为止,谢谢您与我的联系。
随着我对Fragments的了解越来越多,尤其是对lifecyle(实时数据)和导航的了解,我开始发布我的fragment实例已保存(我确实在寻找的行为)。
因此,我没有不断地重新创建我的视图,而是保留了它们的引用,以便在随后对嵌套片段onCreateView
方法的任何调用中重新显示它们。
一段时间以来,它一直运行良好,直到我不得不实现一个外部库,该库使用其自己的自定义嵌套导航公开一个片段(是的,它变得 很复杂-两级嵌套导航!)。
因此,我决定重写BottomNavigationView
的导航。
这是我的问题:重新附加以前分离的Fragment时,内容为空白。而且,在使用背景色之后,我了解到使用#attach
和#detach
确实可以正常工作并且确实隐藏/显示了NestedNavigationFragments
,但是它们的内容无处可见。
使用调试器,我意识到虽然确实调用了我的NestedNavigationFragments
onCreateView
方法,但对于以前显示的嵌套(子)片段却无法说同样的话!
到目前为止,我找到的解决方案(如简介中所述)是不重复使用NestedNavigationFragments
的相同视图。我每次都必须重新创建视图。
这样做会导致嵌套片段onCreateView
最终被调用,并允许它们使用缓存视图!哇拉!
哇……?真的吗好吧,我想不是,如果反过来,一个嵌套的片段开始使用嵌套的导航图。这就是我提到的外部库所发生的事情!值得庆幸的是,我正在使用此库,因此可以对其进行修复。这就是为什么我来到这里,看看我的逻辑是否有误。
这就是为什么在发现这一点后,我开始问您关于重新使用片段的缓存视图的看法。
对于未嵌套的片段,这似乎不会引起任何问题,但是一旦您嵌套了片段,所有地狱就会崩溃。
那是正常的行为吗?我做错什么了吗 ?有更好的方法吗?某些Fragment的观点很沉重,而重新创建它们的成本太高了……
感谢您阅读并期待您的想法和答案!