Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use viewLifecycleOwner as the LifecycleOwner

I have a fragment:

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
        })
    }
}

In my fragment, I have a instance of StudentsViewModel which is initiated in onViewCreated(...).

In, StudentsViewModel, students is a LiveData:

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

Back to MyFragment, in function updateStudentList() I get compiler error complaining the this parameter I passed in to .observe(this, Observer{...}) that Use viewLifecycleOwner as the LifecycleOwner

Why I get this error? How to get rid of it?

like image 213
user842225 Avatar asked Dec 29 '19 17:12

user842225


People also ask

What is view life cycle owner?

viewLifeCycleOwner is LifecycleOwner that represents the Fragment's View lifecycle. In most cases, this mirrors the lifecycle of the Fragment itself, but in cases of detached Fragments, the lifecycle of the Fragment can be considerably longer than the lifecycle of the View itself.

How do I get LifecycleOwner from fragment?

The fragment itself is the LifecycleOwner you are looking for. You can use keyword "this" as a reference to the fragment. Read this: "Lifecycle is a class that holds the information about the lifecycle state of a component (like an activity or a fragment) and allows other objects to observe this state."


4 Answers

Why I get this error?

Lint is recommending that you use the lifecycle of the fragment's views (viewLifecycleOwner) rather than the lifecycle of the fragment itself (this). Ian Lake and Jeremy Woods of Google go over the difference as part of this Android Developer Summit presentation, and Ibrahim Yilmaz covers the differences in this Medium post In a nutshell:

  • viewLifecycleOwner is tied to when the fragment has (and loses) its UI (onCreateView(), onDestroyView())

  • this is tied to the fragment's overall lifecycle (onCreate(), onDestroy()), which may be substantially longer

How to get rid of it?

Replace:

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

with:

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

In your current code, if onDestroyView() is called, but onDestroy() is not, you will continue observing the LiveData, perhaps crashing when you try populating a non-existent RecyclerView. By using viewLifecycleOwner, you avoid that risk.

like image 179
CommonsWare Avatar answered Oct 19 '22 06:10

CommonsWare


viewLifeCycleOwner is LifecycleOwner that represents the Fragment's View lifecycle. In most cases, this mirrors the lifecycle of the Fragment itself, but in cases of detached Fragments, the lifecycle of the Fragment can be considerably longer than the lifecycle of the View itself.

Fragment views get destroyed when a user navigates away from a fragment, even though the fragment itself is not destroyed. This essentially creates two lifecycles, the lifecycle of the fragment, and the lifecycle of the fragment's view. Referring to the fragment's lifecycle instead of the fragment view's lifecycle can cause subtle bugs when updating the fragment's view.

like image 32
Tonnie Avatar answered Oct 19 '22 06:10

Tonnie


Instead of this use viewLifecycleOwner to observe LiveData

viewModel.students.observe(viewLifecycleOwner, Observer {
    //TODO: populate recycler view
})
like image 45
Md. Asaduzzaman Avatar answered Oct 19 '22 05:10

Md. Asaduzzaman


Captain obvious here, also useful could be this:

viewModel.searchConfiguration.observe(requireParentFragment().viewLifecycleOwner, Observer {}
like image 30
Samir Ramic Avatar answered Oct 19 '22 07:10

Samir Ramic