У меня возникла проблема с компонентами новой архитектуры в Котлине, когда я создаю компонент ViewModel в рекомендуемом виде (в методе onCreate ()), результат получается следующим образом:
Вот как я создаю этот
override fun onCreate(savedInstanceState: Bundle?) { AndroidInjection.inject(this) super.onCreate(savedInstanceState) setContentView(R.layout.activity_list) val arrayMap = ArrayMap<Class<out ViewModel>, ViewModel>() arrayMap.put(ListViewModel::class.java, ListViewModel(webApi, repoDao)) val factory = ViewModelFactory(arrayMap) listViewModel = ViewModelProviders.of(this, factory).get(ListViewModel::class.java) listViewModel.items.observe({ this.lifecycle }) { Toast.makeText(this, it?.joinToString { it + " " } ?: "null", Toast.LENGTH_SHORT).show() }
Но когда я использовал Dagger для инъекции ListViewModel, я получил новый экземпляр ListViewModel каждый раз, когда была восстановлена активность. Вот код Dagger ListActivityModel.
@Module @ListActivityScopeclass ListActivityModule { @Provides @ListActivityScope fun provideListViewModel(webApi: WebApi, repoDao: RepoDao, listActivity: ListActivity): ListViewModel { val arrayMap = ArrayMap<Class<out ViewModel>, ViewModel>() arrayMap.put(ListViewModel::class.java, ListViewModel(webApi, repoDao)) val factory = ViewModelFactory(arrayMap) val result = ViewModelProviders.of(listActivity, factory).get(ListViewModel::class.java) return result }
} Затем метод ListActivity onCreate () выглядит так:
override fun onCreate(savedInstanceState: Bundle?) { AndroidInjection.inject(this) super.onCreate(savedInstanceState) setContentView(R.layout.activity_list) listViewModel.items.observe({ this.lifecycle }) { Toast.makeText(this, it?.joinToString { it + " " } ?: "null", Toast.LENGTH_SHORT).show() } }
И есть то, что я заметил после регистрации:
D/ListActivity: ---> onCreate() ListActivity: = [com.example.dom.app.new_arch.ListActivity@a0f2778] D/ListActivity: ---> onCreate() listViewModel: = [com.example.dom.app.new_arch.ListViewModel@54a8e51] //Activity orientation changes E/ViewModelStores: Failed to save a ViewModel for com.example.dom.app.new_arch.ListActivity@a0f2778 D/ListActivity: ---> onCreate() ListActivity: = [com.example.dom.app.new_arch.ListActivity@6813433] D/ListActivity: ---> onCreate() listViewModel: = [com.example.dom.app.new_arch.ListViewModel@55cf3f0]
Ошибка, которую я получил:
ViewModelStores: не удалось сохранить ViewModel для
поставляется с Android класса HolderFragment с пакетом android.arch.lifecycle.
Есть что-то, чего я пропустил, работая с кинжалом и новыми элементами дуги?
То, как я это делаю, – это предоставить только ViewModelFactory
с помощью кинжала. Затем он вводится в действие, и вы вызываете ViewModelProviders.of(listActivity, factory).get(ListViewModel::class.java)
оттуда. Причина, по которой ваш подход не работает, заключается в том, что AndroidInjection.inject()
создаст ViewModel до onCreate, что приведет к неопределенному поведению.
См. Также: https://github.com/googlesamples/android-architecture-components/issues/202
Я не использую AndroidInjection.inject()
потому что он создает новый компонент Dagger. Я создаю компонент Dagger в классе Application, и я использую этот экземпляр компонента для вызова инъекции во всех других местах приложения. Таким образом, ваши синглтоны инициализируются только один раз.