Utilisez viewLifecycleOwner comme LifecycleOwner

17

J'ai un 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
        })
    }
}

Dans mon fragment, j'ai une instance de StudentsViewModel qui est lancée dans onViewCreated(...).

Dans, StudentsViewModel, studentsest un LiveData:

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

Retour à MyFragment, en fonction updateStudentList()je reçois d' erreur du compilateur se plaindre du thisparamètre je suis passé à .observe(this, Observer{...})ceUse viewLifecycleOwner as the LifecycleOwner

Pourquoi je reçois cette erreur? Comment s'en débarrasser?

user842225
la source

Réponses:

34

Pourquoi je reçois cette erreur?

Lint vous recommande d'utiliser le cycle de vie des vues du fragment ( viewLifecycleOwner) plutôt que le cycle de vie du fragment lui-même ( this). Ian Lake et Jeremy Woods de Google passent en revue la différence dans le cadre de cette présentation Android Developer Summit , et Ibrahim Yilmaz couvre les différences dans ce billet moyen. En bref:

  • viewLifecycleOwnerest lié à lorsque le fragment a (et perd) son interface utilisateur ( onCreateView(), onDestroyView())

  • thisest lié au cycle de vie global du fragment ( onCreate(), onDestroy()), qui peut être sensiblement plus long

Comment s'en débarrasser?

Remplacer:

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

avec:

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

Dans votre code actuel, si onDestroyView()est appelé, mais onDestroy()ne l'est pas, vous continuerez à observer le LiveData, peut-être en train de planter lorsque vous essayez de remplir un inexistant RecyclerView. En utilisant viewLifecycleOwner, vous évitez ce risque.

CommonsWare
la source
6
Notez que vous devez toujours utiliser "ceci" en cas de DialogFragment (et probablement tous les fragments qui ne renvoient pas de vue pour onCreateView. Sinon, vous obtiendrez une exception:IllegalStateException: Can't access the Fragment View's LifecycleOwner when getView() is null i.e., before onCreateView() or after onDestroyView()
développeur Android
@androiddeveloper Vous pourriez toujours utiliser lifeCycleOwner dans onViewCreated et au-delà?
jontro
@jontro Je suis sûr que vous le pouvez. Essayez-le et faites-le moi savoir :)
développeur Android
@androiddeveloper semble bien fonctionner!
jontro
1

Au lieu d' thisutiliser viewLifecycleOwnerpour observerLiveData

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