如何将SavedStateHandle 注入到动态特性模块中的ViewModel?
How to inject SavedStateHandle to ViewModel in dynamic feature module?
使用带有 savedStateHandle 和 by viewModels()
的 @Assisted
注释可以将 SavedStateHandle 对象注入到不是带有匕首柄的动态功能模块的模块中的 ViewModel 中
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private val viewModel: MainActivityViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
class MainActivityViewModel @ViewModelInject constructor(
@Assisted savedStateHandle: SavedStateHandle
) : ViewModel() {
val stringData = savedStateHandle.getLiveData<String>("hello_world")
}
但动态特性模块不可能这样做。如何使用动态功能模块 ViewModels 完成?
我的 ViewModel 是
class DashboardViewModel @ViewModelInject constructor(
@Assisted private val savedStateHandle: SavedStateHandle,
private val coroutineScope: CoroutineScope,
private val dashboardStatsUseCase: GetDashboardStatsUseCase,
private val setPropertyStatsUseCase: SetPropertyStatsUseCase
) : ViewModel() {
}
使用
为 SavedStateHandle 创建通用 FragmentFactory
interface ViewModelFactory<out V : ViewModel> {
fun create(handle: SavedStateHandle): V
}
class GenericSavedStateViewModelFactory<out V : ViewModel>(
private val viewModelFactory: ViewModelFactory<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
}
}
/**
* Convenience function to use with `by viewModels` that creates an instance of
* [AbstractSavedStateViewModelFactory] that enables us to pass [SavedStateHandle]
* to the [ViewModel]'s constructor.
*
* @param factory instance of [ViewModelFactory] that will be used to construct the [ViewModel]
* @param owner instance of Fragment or Activity that owns the [ViewModel]
* @param defaultArgs Bundle with default values to populate the [SavedStateHandle]
*
* @see ViewModelFactory
*/
@MainThread
inline fun <reified VM : ViewModel> SavedStateRegistryOwner.withFactory(
factory: ViewModelFactory<VM>,
defaultArgs: Bundle? = null
) = GenericSavedStateViewModelFactory(factory, this, defaultArgs)
ViewModel 的 ViewModel 工厂
class DashboardViewModelFactory @Inject constructor(
private val coroutineScope: CoroutineScope,
private val dashboardStatsUseCase: GetDashboardStatsUseCase,
private val setPropertyStatsUseCase: SetPropertyStatsUseCase
) : ViewModelFactory<DashboardViewModel> {
override fun create(handle: SavedStateHandle): DashboardViewModel {
return DashboardViewModel(
handle,
coroutineScope,
dashboardStatsUseCase,
setPropertyStatsUseCase
)
}
}
并使用 Fragment 中的 DashBoardViewModelFactory 创建 ViewModel
@Inject
lateinit var dashboardViewModelFactory: DashboardViewModelFactory
private val viewModel: DashboardViewModel
by viewModels { withFactory(dashboardViewModelFactory) }
Here 您可以看到完整的实施过程。我找不到我用来实现这个解决方案的来源,如果你可以评论 link,我想感谢作者。
使用带有 savedStateHandle 和 by viewModels()
的 @Assisted
注释可以将 SavedStateHandle 对象注入到不是带有匕首柄的动态功能模块的模块中的 ViewModel 中
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private val viewModel: MainActivityViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
class MainActivityViewModel @ViewModelInject constructor(
@Assisted savedStateHandle: SavedStateHandle
) : ViewModel() {
val stringData = savedStateHandle.getLiveData<String>("hello_world")
}
但动态特性模块不可能这样做。如何使用动态功能模块 ViewModels 完成?
我的 ViewModel 是
class DashboardViewModel @ViewModelInject constructor(
@Assisted private val savedStateHandle: SavedStateHandle,
private val coroutineScope: CoroutineScope,
private val dashboardStatsUseCase: GetDashboardStatsUseCase,
private val setPropertyStatsUseCase: SetPropertyStatsUseCase
) : ViewModel() {
}
使用
为 SavedStateHandle 创建通用FragmentFactory
interface ViewModelFactory<out V : ViewModel> {
fun create(handle: SavedStateHandle): V
}
class GenericSavedStateViewModelFactory<out V : ViewModel>(
private val viewModelFactory: ViewModelFactory<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
}
}
/**
* Convenience function to use with `by viewModels` that creates an instance of
* [AbstractSavedStateViewModelFactory] that enables us to pass [SavedStateHandle]
* to the [ViewModel]'s constructor.
*
* @param factory instance of [ViewModelFactory] that will be used to construct the [ViewModel]
* @param owner instance of Fragment or Activity that owns the [ViewModel]
* @param defaultArgs Bundle with default values to populate the [SavedStateHandle]
*
* @see ViewModelFactory
*/
@MainThread
inline fun <reified VM : ViewModel> SavedStateRegistryOwner.withFactory(
factory: ViewModelFactory<VM>,
defaultArgs: Bundle? = null
) = GenericSavedStateViewModelFactory(factory, this, defaultArgs)
ViewModel 的 ViewModel 工厂
class DashboardViewModelFactory @Inject constructor(
private val coroutineScope: CoroutineScope,
private val dashboardStatsUseCase: GetDashboardStatsUseCase,
private val setPropertyStatsUseCase: SetPropertyStatsUseCase
) : ViewModelFactory<DashboardViewModel> {
override fun create(handle: SavedStateHandle): DashboardViewModel {
return DashboardViewModel(
handle,
coroutineScope,
dashboardStatsUseCase,
setPropertyStatsUseCase
)
}
}
并使用 Fragment 中的 DashBoardViewModelFactory 创建 ViewModel
@Inject
lateinit var dashboardViewModelFactory: DashboardViewModelFactory
private val viewModel: DashboardViewModel
by viewModels { withFactory(dashboardViewModelFactory) }
Here 您可以看到完整的实施过程。我找不到我用来实现这个解决方案的来源,如果你可以评论 link,我想感谢作者。