Використовуйте viewLifecycleOwner як LifecycleOwner


17

У мене є фрагмент:

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

У своєму фрагменті у мене є екземпляр StudentViewModel, який ініційований у onViewCreated(...).

В, StudentsViewModel, studentsє LiveData:

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

Назад MyFragment, у функції updateStudentList()я отримую помилку компілятора, скаржившись на thisпараметр, який я передав до .observe(this, Observer{...})цьогоUse viewLifecycleOwner as the LifecycleOwner

Чому я отримую цю помилку? Як позбутися від цього?

Відповіді:


32

Чому я отримую цю помилку?

Lint рекомендує використовувати життєвий цикл поглядів фрагмента ( viewLifecycleOwner), а не життєвий цикл самого фрагмента ( this). Ієн Лейк та Джеремі Вудс із Google вирішують різницю в рамках цієї презентації на вищому рівні для розробників Android , а Ібрагім Йілмаз висвітлює відмінності у цій середній публікації :

  • viewLifecycleOwnerприв’язується до того, коли фрагмент має (і втрачає) свій інтерфейс користувача ( onCreateView(), onDestroyView())

  • thisприв’язаний до загального життєвого циклу фрагмента ( onCreate(), onDestroy()), який може бути значно довшим

Як позбутися від цього?

Замінити:

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

з:

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

У вашому поточному коді, якщо onDestroyView()він викликається, але onDestroy()це не так, ви продовжуватимете спостерігати за тим LiveData, що може бути збій, коли ви намагаєтесь заповнити неіснуючий RecyclerView. Використовуючи viewLifecycleOwner, ви уникаєте цього ризику.


6
Зауважте, що ви все-таки повинні використовувати "це" у випадку DialogFragment (і, ймовірно, кожен фрагмент, який не повертає вигляд для onCreateView. Інакше ви отримаєте виняток:IllegalStateException: Can't access the Fragment View's LifecycleOwner when getView() is null i.e., before onCreateView() or after onDestroyView()
android developer

@androiddeveloper Ви все ще можете використовувати lifeCycleOwner в onViewCreate і далі?
jontro

@jontro Досить впевнений, що зможеш. Спробуйте і повідомте мені :)
андроїд розробник

@androiddeveloper, здається, працює добре!
jontro

1

Замість thisвикористання viewLifecycleOwnerдля спостереженняLiveData

viewModel.students.observe(viewLifecycleOwner, Observer {
    //TODO: populate recycler view
})
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.