使用 viewLifecycleOwner 作为 LifecycleOwner

Use viewLifecycleOwner as the LifecycleOwner

我有一个片段:

class MyFragment : BaseFragment() {

   // my StudentsViewModel instance
   lateinit var viewModel: StudentsViewModel

   override fun onCreateView(...){
        ...
   }

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

       viewModel = ViewModelProviders.of(this).get(StudentsViewModel::class.java)
       updateStudentList()
   }

   fun updateStudentList() {
        // Compiler error on 'this': Use viewLifecycleOwner as the LifecycleOwner
        viewModel.students.observe(this, Observer {
            //TODO: populate recycler view
        })
    }
}

在我的片段中,我有一个在 onViewCreated(...) 中启动的 StudentsViewModel 实例。

中,StudentsViewModelstudents是一个LiveData

class StudentsViewModel : ViewModel() {
    val students = liveData(Dispatchers.IO) {
          ...
    }
}

返回 MyFragment,在函数 updateStudentList() 中,我收到编译器错误,抱怨我传递给 .observe(this, Observer{...})this 参数 Use viewLifecycleOwner as the LifecycleOwner

为什么我会收到这个错误?如何摆脱它?

代替this使用viewLifecycleOwner观察LiveData

viewModel.students.observe(viewLifecycleOwner, Observer {
    //TODO: populate recycler view
})

Why I get this error?

Lint 建议您使用片段视图的生命周期 (viewLifecycleOwner) 而不是片段本身的生命周期 (this)。 Google 的伊恩·雷克 (Ian Lake) 和杰里米·伍兹 (Jeremy Woods) 在 this Android Developer Summit presentation, and Ibrahim Yilmaz covers the differences in this Medium post 中回顾了差异 简而言之:

  • viewLifecycleOwner 与片段具有(和丢失)其 UI (onCreateView(), onDestroyView())

    相关联
  • this 与片段的整个生命周期相关(onCreate()onDestroy()),可能会长得多

How to get rid of it?

替换:

viewModel.students.observe(this, Observer {
        //TODO: populate recycler view
    })

与:

viewModel.students.observe(viewLifecycleOwner, Observer {
        //TODO: populate recycler view
    })

在您当前的代码中,如果 onDestroyView() 被调用,但 onDestroy() 未被调用,您将继续观察 LiveData,当您尝试填充不存在的 RecyclerView。通过使用 viewLifecycleOwner,您可以避免这种风险。

viewLifeCycleOwner是代表Fragment的View生命周期的LifecycleOwner。在大多数情况下,这反映了片段本身的生命周期,但在分离片段的情况下,片段的生命周期可能比视图本身的生命周期长得多。

当用户离开片段时,片段视图会被破坏,即使片段本身没有被破坏。这实质上创建了两个生命周期,片段的生命周期和片段视图的生命周期。在更新片段视图时,引用片段的生命周期而不是片段视图的生命周期可能会导致细微的错误。

这里的队长很明显,也有用的可能是这个:

viewModel.searchConfiguration.observe(requireParentFragment().viewLifecycleOwner, Observer {}