导航架构片段重载问题

Posted

技术标签:

【中文标题】导航架构片段重载问题【英文标题】:Navigation Architecture Fragment Reload Problem 【发布时间】:2019-06-14 15:10:07 【问题描述】:

我在图片库中使用导航架构,当我从片段 A 转到 B 然后返回到 A 时,这 3 个方法再次调用,这将导致我的画廊重新加载,我应该在片段中加载我的数据,这样当我从 B 回到 A 时,我的方法不会被调用? :

    OnCreateView OnViewCreated OnResume

【问题讨论】:

你找到解决办法了吗? 此问题的解决方案是将列表保存在全局变量或 A Presenter(MVP) 或 ViewModel 中。如果列表存在,请不要进行 api 调用 @AVEbrahimi 你解决了这个问题吗? 【参考方案1】:

诀窍是不要在 onCreateView() 中再次膨胀视图。这将再次调用您的所有生命周期事件,但这将是您维护片段状态的方式。

这是 google android 团队的 Ian Lake 建议的。这是reference。

var binding: FragmentFeedsBinding? = null

   override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? 
    if (binding == null)
        binding = FragmentFeedsBinding.inflate(inflater, container, false)
    return binding?.root

【讨论】:

【参考方案2】:

navigate(...)FragmentNavigator 使用Fragment.instantiate(...) 实现。在提供的示例中,我建议调用 popBackStack() 而不是 navigate(...) 以返回上一个片段

【讨论】:

onViewCreated 仍然被调用【参考方案3】:

片段的生命周期方法无论如何都会再次调用。您可以谷歌它如何使用片段或活动生命周期。

如何处理生命周期的主要思想包括保存视图状态、持久化数据等。如果您正在使用片段,您可以使用保留片段:只需在您的图库片段中放置标志setRetainInstance(true),系统将不会调用例如,onCreate()onDestroy() 方法,同时您将旋转手机。下一步我推荐你使用2017年推出的AndroidArchitectureComponent You can read about it here.

在你的情况下,我猜你应该为你的片段创建 ViewModel,在你的 ViewModel 中加载数据并将数据放入 LiveData 对象中。此外,您应该覆盖片段中的 onCreate 并使片段保留(如何做到这一点我刚刚描述过)并在此处初始化您的 ViewModel。之后,在 onViewCreated 或 onActivityCreated 中,您需要通过 LiveData 和 ViewModel 观察您的数据,并且无需重新加载即可显示它。

这是基本算法。类似的行为可以通过不同的方法实现,例如 MVP、RxPM、MVVM(基于 RxJava 和 RxAndroid)等。我想在这里描述所有这些模式并不是我回答的主要目的。互联网上有很多信息(在 *** 上也是如此),请尝试查找。

它的主要思想是,您应该在对象中加载一些可以在视图销毁时仍然存在的东西,并在视图准备好时告诉视图从该对象获取可用数据。

【讨论】:

【参考方案4】:

我也面临同样的问题,即我的片段(例如 片段 A)在从其他片段(片段 B)。我试图找出有效的解决方案,但找不到相同的解决方案。目前,我已经使用 Fragment 生命周期完成了一个临时解决方案。当我们popBackStack()一个fragment(Fragment B),另一个进入前台的fragment(Fragment A),它的onCreateView()onViewCreated()会被调用.所以我已经使用这个生命周期管理了状态。第一次时,我们的 Fragment A 将启动,它的onAttach() 函数将运行,我将片段状态保存为:

override fun onAttach(context: Context) 
    super.onAttach(context)
    fragmentStatus = "onAttach"

在onViewCreated()之后,我把这个状态改成了:

fragmentStatus = "onViewCreated"

onViewCreated() 内部,我正在检查这个状态值

if (fragmentStatus == "onAttach") 
        fragmentStatus = "onViewCreated"
//Write your code here for rest of the functionality

所以现在每当这个 Fragment A 进入前台时,它总是会找到onViewCreated 的状态,直到这个 Fragment 被销毁并重新启动。

注意:这是避免在该 Fragment 中重新加载您的工作的临时解决方案,但系统会根据需要重新启动该 Fragment。

【讨论】:

【参考方案5】:

您可以使用 ViewModel 来保留数据并保持滚动位置。在 Android 的导航组件中,片段的 OnViewCreated 和 onCreateView 会在每次某些片段导航时被调用。将数据保存在 ViewModel 中,以免被破坏

【讨论】:

以上是关于导航架构片段重载问题的主要内容,如果未能解决你的问题,请参考以下文章

使用导航架构组件添加(而不是替换)片段

在 FAB 单击时导航到片段(导航架构组件)

导航架构组件 - 对话框片段

导航架构组件 - 导航抽屉

Jetpack 组成没有片段的导航架构?

如何使用导航架构组件从片段中获取结果?