如何从 AbstractSavedStateViewModelFactory 动态设置包
How to dynamically set the bundle from AbstractSavedStateViewModelFactory
我的 ViewModelFactory:
class ViewModelFactory @Inject constructor(
private val viewModelMap: MutableMap<Class<out ViewModel>, ViewModelAssistedFactory<out ViewModel>>,
owner: SavedStateRegistryOwner,
defaultArgs: Bundle?
) : AbstractSavedStateViewModelFactory(owner, defaultArgs) {
@Throws(IllegalStateException::class)
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(key: String, modelClass: Class<T>, handle: SavedStateHandle): T {
return viewModelMap[modelClass]?.create(handle) as? T ?: throw IllegalStateException("Unknown ViewModel class")
}
}
Activity:
@Inject
lateinit var viewModelFactory: ViewModelFactory
protected val viewModel: ViewModel by lazy { ViewModelProvider(this, viewModelFactory).get(getViewModelClass()) }
ViewModel:
@AssistedInject.Factory
interface Factory : ViewModelAssistedFactory<SplashViewModel>
我想知道如何动态提供 defaultArgs 而不是:
Activity模块
@Module
companion object {
@JvmStatic
@Nullable
@Provides
fun provideDefaultArgs(): Bundle? {
return null
}
}
我们的想法是可以向 ViewModel 发送一个参数,比方说一个 DetailActivity 的 ID。
通常我使用 "init" 方法,但如果我可以使用 StateHandle map
会更好。类似于 this and this。
有道理吗?可能吗?
我遇到了 2 个解决方案:
方案一:
将我们的 ViewModelFactory 更改为:
class ViewModelFactory @Inject constructor(
private val viewModelMap: MutableMap<Class<out ViewModel>, ViewModelAssistedFactory<out ViewModel>>
) {
fun create(owner: SavedStateRegistryOwner, defaultArgs: Bundle? = null): AbstractSavedStateViewModelFactory {
return object : AbstractSavedStateViewModelFactory(owner, defaultArgs) {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(key: String, modelClass: Class<T>, handle: SavedStateHandle): T {
return viewModelMap[modelClass]?.create(handle) as? T ?: throw IllegalStateException("Unknown ViewModel class")
}
}
}
}
最后:
@Inject
lateinit var viewModelFactory: ViewModelFactory
protected val viewModel: ViewModel by lazy { ViewModelProvider(this, viewModelFactory.create(this, args).get(getViewModelClass()) }
此外,我们可以将 ActivityModule 简化为(示例):
@AssistedModule
@Module(includes = [AssistedInject_SplashActivityModule::class])
abstract class SplashActivityModule{
@Binds
@IntoMap
@ViewModelKey(SplashViewModel::class)
abstract fun bindFactory(factory: SplashViewModel.Factory): ViewModelAssistedFactory<out ViewModel>
}
Tomáš Mlynarič 的 post 帮助解决了这个问题。
方案B:
创建一个 Factory
没有注入依赖项:
class ViewModelFactoryAlt<out V : ViewModel>(
private val viewModelFactory: ViewModelAssistedFactory<V>,
owner: SavedStateRegistryOwner,
defaultArgs: Bundle? = null
) : AbstractSavedStateViewModelFactory(owner, defaultArgs) {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(key: String, modelClass: Class<T>, handle: SavedStateHandle): T {
return viewModelFactory.create(handle) as T
}
}
创建我们的 ViewModelAssitedFactory
喜欢:
class HelloWorldViewModelFactory @Inject constructor(
private val dependencyA: DependencyA,
...
) : ViewModelAssistedFactory<HelloWorldViewModel> {
override fun create(stateHandle: SavedStateHandle): HelloWorldViewModel {
return HelloWorldViewModel(stateHandle, dependencyA, ...)
}
}
最后:
@Inject
lateinit var factory: HelloWorldViewModelFactory
private val viewModel: HelloWorldViewModel by viewModels { ViewModelFactoryAlt(factory, this, intent.extras) }
Elye 的 post 帮助解决了这个问题。
我的 ViewModelFactory:
class ViewModelFactory @Inject constructor(
private val viewModelMap: MutableMap<Class<out ViewModel>, ViewModelAssistedFactory<out ViewModel>>,
owner: SavedStateRegistryOwner,
defaultArgs: Bundle?
) : AbstractSavedStateViewModelFactory(owner, defaultArgs) {
@Throws(IllegalStateException::class)
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(key: String, modelClass: Class<T>, handle: SavedStateHandle): T {
return viewModelMap[modelClass]?.create(handle) as? T ?: throw IllegalStateException("Unknown ViewModel class")
}
}
Activity:
@Inject
lateinit var viewModelFactory: ViewModelFactory
protected val viewModel: ViewModel by lazy { ViewModelProvider(this, viewModelFactory).get(getViewModelClass()) }
ViewModel:
@AssistedInject.Factory
interface Factory : ViewModelAssistedFactory<SplashViewModel>
我想知道如何动态提供 defaultArgs 而不是:
Activity模块
@Module
companion object {
@JvmStatic
@Nullable
@Provides
fun provideDefaultArgs(): Bundle? {
return null
}
}
我们的想法是可以向 ViewModel 发送一个参数,比方说一个 DetailActivity 的 ID。
通常我使用 "init" 方法,但如果我可以使用 StateHandle map
会更好。类似于 this and this。
有道理吗?可能吗?
我遇到了 2 个解决方案:
方案一:
将我们的 ViewModelFactory 更改为:
class ViewModelFactory @Inject constructor(
private val viewModelMap: MutableMap<Class<out ViewModel>, ViewModelAssistedFactory<out ViewModel>>
) {
fun create(owner: SavedStateRegistryOwner, defaultArgs: Bundle? = null): AbstractSavedStateViewModelFactory {
return object : AbstractSavedStateViewModelFactory(owner, defaultArgs) {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(key: String, modelClass: Class<T>, handle: SavedStateHandle): T {
return viewModelMap[modelClass]?.create(handle) as? T ?: throw IllegalStateException("Unknown ViewModel class")
}
}
}
}
最后:
@Inject
lateinit var viewModelFactory: ViewModelFactory
protected val viewModel: ViewModel by lazy { ViewModelProvider(this, viewModelFactory.create(this, args).get(getViewModelClass()) }
此外,我们可以将 ActivityModule 简化为(示例):
@AssistedModule
@Module(includes = [AssistedInject_SplashActivityModule::class])
abstract class SplashActivityModule{
@Binds
@IntoMap
@ViewModelKey(SplashViewModel::class)
abstract fun bindFactory(factory: SplashViewModel.Factory): ViewModelAssistedFactory<out ViewModel>
}
Tomáš Mlynarič 的 post 帮助解决了这个问题。
方案B:
创建一个 Factory
没有注入依赖项:
class ViewModelFactoryAlt<out V : ViewModel>(
private val viewModelFactory: ViewModelAssistedFactory<V>,
owner: SavedStateRegistryOwner,
defaultArgs: Bundle? = null
) : AbstractSavedStateViewModelFactory(owner, defaultArgs) {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(key: String, modelClass: Class<T>, handle: SavedStateHandle): T {
return viewModelFactory.create(handle) as T
}
}
创建我们的 ViewModelAssitedFactory
喜欢:
class HelloWorldViewModelFactory @Inject constructor(
private val dependencyA: DependencyA,
...
) : ViewModelAssistedFactory<HelloWorldViewModel> {
override fun create(stateHandle: SavedStateHandle): HelloWorldViewModel {
return HelloWorldViewModel(stateHandle, dependencyA, ...)
}
}
最后:
@Inject
lateinit var factory: HelloWorldViewModelFactory
private val viewModel: HelloWorldViewModel by viewModels { ViewModelFactoryAlt(factory, this, intent.extras) }
Elye 的 post 帮助解决了这个问题。