android - 如何在使用导航组件导航时保存 fragment 状态

标签 android android-fragments kotlin

我正在尝试使用 android 架构组件创建单个 Activity 应用程序。我有一个包含一些文本字段的 fragment A,当用户按下按钮时,我导航到 fragment B,在该应用程序使用如下代码导航回 A 后,他上传并编辑了一些图像:
findNavController().navigate(R.id.action_from_B_to_A, dataBundle)
当返回 B 时,使用 dataBundle 将一些数据传递给 A .问题在于所有文本字段都重置了,因为 fragment A 基本上是从头开始重新创建的。我在某处读到谷歌的开发人员建议您可以将 View 保存在 var 中,而不是每次都对其进行膨胀。所以尝试这样做:

private var savedViewInstance: View? = null

override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
): View? {
    return if (savedViewInstance != null) {
        savedViewInstance
    } else {
        savedViewInstance =
                inflater.inflate(R.layout.fragment_professional_details, container, false)
        savedViewInstance
    }
}

但这不起作用,导航回 A 时所有文本字段都会重置。我做错了什么?处理此类案件的正确方法是什么?

最佳答案

我会一一回答你的问题。

But this does not work, all the textfields reset when navigating back to A. What am I doing wrong?



从 FragmentB,当用户完成工作并且应用调用以下方法返回 FragmentA。
findNavController().navigate(R.id.action_from_B_to_A, dataBundle)

您希望应用程序将用户带回 FragmentA,但实际结果是创建了一个新的 FragmentA 并将其放在后堆栈的顶部。现在后栈将是这样的。
FragmentA (new instance)
FragmentB
FragmentA (old instance)

这就是为什么您会看到所有文本字段都重置的原因,因为它是 FragmentA 的全新实例。

What is proper way of handling cases like this?



你想开始一个 fragment ,然后从那个 fragment 接收结果,看起来像 startActivityForResult Activity 方法。

Android Dev Summit 2019 - Architecture Components ,在2:43,有一个Android开发者的问题。

Can we have something like startFragmentForResult for the Navigation Controller?



答案是他们正在努力,这个功能将在 future 推出。

回到你的问题,这是我的解决方案。

第一步:创建一个名为 SharedViewModel 的类
class SharedViewModel : ViewModel() {

    // This is the data bundle from fragment B to A
    val bundleFromFragmentBToFragmentA = MutableLiveData<Bundle>()
}

第二步:将这些代码行添加到 FragmentA
private lateinit var viewModel: SharedViewModel

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    viewModel = ViewModelProviders.of(requireActivity()).get(SharedViewModel::class.java)
    viewModel.bundleFromFragmentBToFragmentA.observe(viewLifecycleOwner, Observer {
        // This will execute when fragment B set data for `bundleFromFragmentBToFragmentA`
        // TODO: Write your logic here to handle data sent from FragmentB
        val message = it.getString("ARGUMENT_MESSAGE", "")
        Toast.makeText(requireActivity(), message, Toast.LENGTH_SHORT).show()
    })
}

第三步:将这些代码行添加到 FragmentB
// 1. Declare this as class's variable
private lateinit var viewModel: SharedViewModel

// 2. Use the following code when you want to return FragmentA           
// findNavController().navigate(R.id.action_from_B_to_A) // Do not use this one

// Set data for `bundleFromFragmentBToFragmentA`
val data = Bundle().apply { putString("ARGUMENT_MESSAGE", "Hello from FragmentB") }
viewModel.bundleFromFragmentBToFragmentA.value = data

// Pop itself from back stack to return FragmentA
requireActivity().onBackPressed()

关于android - 如何在使用导航组件导航时保存 fragment 状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59629541/

相关文章:

android - 从微调器获取文本

android - 完全断开蓝牙低功耗设备

Android Fragment Transition - 动画期间避免GC

gradle - 在 Gradle Kotlin DSL 中注册和创建有什么区别

java - 为什么允许从静态对象进行非静态引用?

java - 安卓 :Export Android Project as jar

android-fragments - 从片段设置半透明状态栏

java - 构造函数参数 "this"从 Activity 但从 Fragment 工作

java - 列出 spring-boot 中目录的文件

android - 如何在 Jetpack Compose 中分分钟重构?