26

我在我的项目中使用 Jetpack 导航组件,其中包含一个活动和一些片段。

我有一个带有从服务器端填充的列表的片段。然后我调用getDataFromServeronViewCreated方法,当用户单击一个项目时,会显示一个新片段。

问题是当我按下后退按钮时,onViewCreated在我的列表片段中再次调用。

那么,我怎样才能防止我的第一个片段再次重新创建呢?我不想要不必要onViewCreated的电话。

4

4 回答 4

4

当然,我们不能阻止调用 oncrateView,但是有一个简单的方法。我们可以在初始化 ViewModel 时调用它,而不是在 onCreateView 或其他生命周期方法中调用 view.loadData()

这篇文章帮助我更好地了解 ViewModel 使用架构组件时的 5 个常见错误

更新:

当前的导航组件(V 2.3.0)不支持此功能,它总是在导航到另一个片段时杀死片段。想象一下,您在 Fragment A 中有谷歌地图,因此每次返回 Fragment 时,它都会再次初始化,并且相机会移动到用户位置!(真是个坏主意)。

因此,如果您有同样的问题,最好的方法是不要使用导航组件。

导航、保存片段状态、GitHub 问题

更新 2:

在某些情况下,例如过滤器或分页,我们可以在 ViewModel 中使用 switchMap 之类的转换,而不是在 init 函数中获取数据。

更新 3:

如果您必须调用函数来从源加载数据,有很多方法可以防止再次调用该函数,第一种也是最简单的方法是在视图中调用 getData(),而不是调用 ViewModel 初始化函数。第二个是使用惰性变量,另一个是在 livedata 上使用 SwitchMap。有关更多信息,您可以在此处找到所有解决方案

于 2020-03-18T17:40:15.800 回答
1

也许你已经激活了图表。

app:popUpTo="@+id/nav_fingerprint_capture"
app:popUpToInclusive="true"
于 2020-02-20T21:39:04.693 回答
0

Jetpack 导航组件替换了片段。它不会将片段添加到堆栈中。因此,当您从 Fragment A 打开 Fragment B 并单击 Fragment A 中的返回按钮时,会重新创建 Fragment B。

如果片段 A 中有 API 调用,并且您不想在每个片段重新创建时进行 API 调用,那么您可以将 API 响应保存在视图模型中,并在片段重新创建时重用响应。

例子:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    if(foodViewModel.foodDataList.isEmpty()) {
        //make API call here and
        //save the response in foodViewModel.foodDataList
    } else {
        //use the saved response from viewmodel
        //and populate recyclerview
    }
于 2021-04-20T12:42:46.727 回答
0

当按下后退按钮时,您无法阻止调用 onViewCreated 方法或片段的任何方法,因此您应该更好地将视图模型与列表片段一起使用,并从视图模型中的服务器获取数据。避免在片段中从服务器获取数据,因为您已经在使用导航 UI。

于 2019-02-07T02:50:05.320 回答