Используйте 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
        })
    }
}

В моем фрагменте у меня есть экземпляр StudentsViewModel, который инициируется в onViewCreated(...).

В, StudentsViewModel, studentsявляется LiveData:

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

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

Почему я получаю эту ошибку? Как от этого избавиться?

user842225
источник

Ответы:

34

Почему я получаю эту ошибку?

Lint рекомендует использовать жизненный цикл представлений фрагмента ( viewLifecycleOwner), а не жизненный цикл самого фрагмента ( this). Ян Лэйк и Джереми Вудс из Google рассматривают разницу в рамках этой презентации на Android Developer Summit , а Ибрагим Йилмаз рассказывает о различиях в этой публикации среднего уровня. В двух словах:

  • 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, вы избегаете этого риска.

CommonsWare
источник
6
Обратите внимание, что вы все равно должны использовать «this» в случае DialogFragment (и, вероятно, каждый фрагмент, который не возвращает представление для onCreateView. В противном случае вы получите исключение:IllegalStateException: Can't access the Fragment View's LifecycleOwner when getView() is null i.e., before onCreateView() or after onDestroyView()
Android-разработчик
@androiddeveloper Вы все еще можете использовать lifeCycleOwner в onViewCreated и далее?
Jontro
@jontro Уверен, что можешь. Попробуйте и дайте мне знать :)
Android-разработчик
@androiddeveloper отлично работает!
jontro
1

Вместо того, чтобы thisиспользовать, viewLifecycleOwnerчтобы наблюдатьLiveData

viewModel.students.observe(viewLifecycleOwner, Observer {
    //TODO: populate recycler view
})
Мд. Асадуззаман
источник