如何从AbstractSavedStateViewModelFactory中动态设置捆绑。

问题描述 投票:2回答:1

我的 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")
    }
}

活动:

@Inject
lateinit var viewModelFactory: ViewModelFactory
protected val viewModel: ViewModel by lazy { ViewModelProvider(this, viewModelFactory).get(getViewModelClass()) }

查看模型:

@AssistedInject.Factory
interface Factory : ViewModelAssistedFactory<SplashViewModel>

我想知道如何动态提供defaultArgs,而不是。

ActivityModule

@Module
    companion object {
        @JvmStatic
        @Nullable
        @Provides
        fun provideDefaultArgs(): Bundle? {
            return null
        }
    }

我们的想法是有可能向ViewModel发送一个参数,比如说一个DetailActivity的ID。StateHandle map 会更好。类似于... 这个这个.

有意义吗?可以吗?

android dagger-2 android-lifecycle android-viewmodel viewmodel-savedstate
1个回答
2
投票

我遇到了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č 帮忙解决了这个问题。

解决方案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 帮忙解决了这个问题。

© www.soinside.com 2019 - 2024. All rights reserved.