我用 MVVM 模式开发应用程序。我想在用户旋转屏幕时保存 UI。
MyViewModel.kt
class MyViewModel(val repository: SomeRepository,
state : SavedStateHandle) : ViewModel() {
private val savedStateHandle = state
companion object {
const val KEY = "KEY"
}
fun saveCityId(cityId: String) {
savedStateHandle.set(CITY_KEY, cityId)
}
fun getCityId(): String? {
return savedStateHandle.get(CITY_KEY)
}
}
ViewModelFactory.kt
@Suppress("UNCHECKED_CAST")
class ViewModelFactory(
private val repository: SomeRepository,
private val state: SavedStateHandle
) : ViewModelProvider.NewInstanceFactory() {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return MyViewModel(repository,state) as T
}
}
我在 MainActivity 中调用它
MainActivity.kt
class MainActivity: AppCompatActivity(), KodeinAware {
private val factory: ViewModelFactoryby instance()
override val kodein by kodein()
private lateinit var viewModel: MyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
cityId = intent.getStringExtra("cityId") ?: viewModel.getCityId()
if (cityId != null) {
viewModel.saveCityId(cityId!!)
viewModel.getCurrentWeather(cityId!!)
}
}
在这里我注入(inject)依赖项
申请.kt
class ForecastApplication: Application(), KodeinAware {
override val kodein = Kodein.lazy {
import(androidXModule(this@ForecastApplication))
bind<SomeApi>() with singleton {
Retrofit.create()
}
bind<WeatherRepository>() with singleton {
WeatherRepository(instance())
}
bind() from provider {
WeatherViewModelFactory(
instance(), instance()
)
}
}
}
我有这个错误
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.simpleforecast/com.example.simpleapp.UI.Cities.Activity}:org.kodein.di.Kodein$NotFoundException: No binding found for bind<SavedStateHandle>()
with ?<Activity>().? { ? }
我应该如何构建 ViewModelFactory 并为 ViewModel 注入(inject) Saved State 模块?
最佳答案
SavedStateHandle
是不能绑定(bind)到 DI 图的参数,因为它是从 Fragment
检索的(或 Activity
),因此您需要执行几个步骤才能使其工作:
1) DI viewmodel 定义 - 因为你有自定义参数,你需要使用 from factory
:
bind() from factory { handle: SavedStateHandle ->
WeatherViewModel(
state = handle,
repository = instance()
)
}
2) ViewModel Factory - 您需要从
AbstractSavedStateViewModelFactory
继承val vmFactory = object : AbstractSavedStateViewModelFactory(this, arguments) {
override fun <T : ViewModel> create(key: String, modelClass: Class<T>, handle: SavedStateHandle): T {
val vmFactory: ((SavedStateHandle) -> WeatherViewModel) = kodein.direct.factory()
return vmFactory(handle) as T
}
}
create
的内部从 DI 图中检索工厂的方法(从步骤 1 开始)。3)您使用指定的工厂检索 ViewModel:
lateinit var vm : WeatherViewModel
fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
vm = ViewModelProvider(this, vmFactory)[WeatherViewModel::class.java]
}
或安卓 KTX 方式:
val vm : WeatherViewModel by viewModels { vmFactory }
关于android - 使用 kodein 在 ViewModelFactory 中注入(inject)保存的状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60762599/