Не удается создать экземпляр класса ViewModel class

#android #kotlin #android-viewmodel #android-mvvm

#Android #kotlin #android-viewmodel #android-mvvm

Вопрос:

  • Я пытаюсь следовать шаблону MVVM в своем приложении для Android, но получаю ошибку при создании экземпляра ViewModel.
  • Ошибка: Cannot create an instance of class DemoViewModel class .

Вот мой код:

DemoFragment.kt:

 class DemoFragment : Fragment(R.layout.fragment_demo) {

    lateinit var mViewModel: DemoViewModel

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        mViewModel=ViewModelProvider(this).get(DemoViewModel::class.java)
        mViewModel.getSomeData()
    }
}
 

DemoViewModel.kt:

 class DemoViewModel(val demoRepository: DemoRepository) : ViewModel() {

    fun getSomeData() {
        Log.d("DemoViewModel", "${demoRepository.getData()}")
    }
}
 

DemoRepository.kt:

 interface DemoRepository {
    fun getData(): Boolean
}

class DemoImpl : DemoRepository {
    override fun getData() = false
}
 

Ответ №1:

Вам нужно использовать ViewModelFactory. Потому что в вашем основном сборщике есть «demoRepository».

     class DemoViewModelFactory constructor(private val repository:DemoImpl): ViewModelProvider.Factory {

     override fun <T : ViewModel> create(modelClass: Class<T>): T {
        return if (modelClass.isAssignableFrom(DemoViewModel::class.java!!)) {
            DemoViewModel(this.repository) as T
        } else {
            throw IllegalArgumentException("ViewModel Not Found")
        }
    }
}
 

Использование

 viewModel = ViewModelProvider(this, DemoViewModelFactory(repositoryObject)).get(DemoViewModel::class.java)
 

Комментарии:

1. Можете ли вы предоставить ответ с примером?

2. Но как я могу инициализировать DemoRepository для передачи в конструкторе DemoViewModelFactory?

3. репозиторий val = DemoRepository() 🙂

4. Но это интерфейс! У вас что-то есть?

5. Это приведено выше.

Ответ №2:

Я бы посоветовал вам использовать функцию расширения «by ViewModels ()», чтобы легко создать экземпляр ViewModel. Обратите внимание, что для его использования необходимо добавить следующую зависимость:

 implementation 'androidx.fragment:fragment-ktx:1.2.5'
 

Пример реализации фрагмента:

 class DemoFragment : Fragment() {

   // Use the 'by ViewModels()' Kotlin property delegate
   // from the fragment-ktx artifact
   private val model: DemoViewModel by viewModels()

   override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
      super.onViewCreated(view, savedInstanceState)
      model.selected.observe(viewLifecycleOwner, Observer<Item> { item ->
        // Update the UI
      })
   }
}
 

Затем вы можете внедрить экземпляр своего репозитория с помощью конструктора с помощью Dagger или Hilt и т. Д.

Комментарии:

1. Так что мне не придется использовать ViewModelFactory, когда в моем классе репозитория есть параметры или нет?

2. Вы должны внедрить свой репозиторий в свою ViewModel через его конструктор. Поначалу это может показаться необязательным, но это хорошая привычка, чтобы сделать ваш код хорошо организованным и тестируемым. Пожалуйста, найдите ниже пример, который я только что сделал с помощью HILT: github.com/bakikocak/Android-MVVM-Sample/blob/main/app/src/main /…

3. Идея в основном состоит в том, чтобы иметь пользовательский интерфейс (Activity, Fragment) настолько простым, насколько это возможно. Так что ваш фрагмент ничего не должен знать о репозитории. Он должен только наблюдать за изменениями в ViewModel и вносить изменения в пользовательский интерфейс.