Tengo un fragmento:

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

En mi fragmento, tengo una instancia de StudentsViewModel que se inicia en onViewCreated(...).

En StudentsViewModel, students es un LiveData:

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

De vuelta a MyFragment, en la función updateStudentList() recibo un error del compilador quejándose del parámetro this que pasé a .observe(this, Observer{...}) que Use viewLifecycleOwner as the LifecycleOwner

¿Por qué me sale este error? Cómo deshacerse de él?

37
user842225 29 dic. 2019 a las 20:28

2 respuestas

La mejor respuesta

¿Por qué me sale este error?

Lint recomienda que utilice el ciclo de vida de las vistas del fragmento (viewLifecycleOwner) en lugar del ciclo de vida del fragmento en sí (this). Ian Lake y Jeremy Woods de Google revisan la diferencia como parte de esta presentación de Android Developer Summit , e Ibrahim Yilmaz cubre las diferencias en esta publicación mediana en una cascara de nuez:

  • viewLifecycleOwner está vinculado cuando el fragmento tiene (y pierde) su IU (onCreateView(), onDestroyView())

  • this está vinculado al ciclo de vida general del fragmento (onCreate(), onDestroy()), que puede ser sustancialmente más largo

Cómo deshacerse de él?

Reemplazar:

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

Con:

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

En su código actual, si se llama a onDestroyView(), pero no a onDestroy(), continuará observando el LiveData, tal vez se bloquee cuando intente llenar un RecyclerView inexistente. Al usar viewLifecycleOwner, evitas ese riesgo.

4
CommonsWare 29 dic. 2019 a las 17:35

En lugar de this use viewLifecycleOwner para observar LiveData

viewModel.students.observe(viewLifecycleOwner, Observer {
    //TODO: populate recycler view
})
0
Md. Asaduzzaman 29 dic. 2019 a las 17:35