the*_*e64 12 android kotlin android-jetpack-compose dagger-hilt navigation-compose
我有一个名为 的可组合项ParentScreen和一个ViewModel名为ParentViewModel. 在 中ParentViewModel,我正在从我的存储库中收集一个值。
class MyRepo @Inject constructor() {
fun getParentData() = System.currentTimeMillis().toString() // some dummy value
}
@HiltViewModel
class ParentViewModel @Inject constructor(
myRepo: MyRepo
) : ViewModel() {
private val _parentData = MutableStateFlow("")
val parentData = _parentData.asStateFlow()
init {
val realData = myRepo.getParentData()
_parentData.value = realData
}
}
@Composable
fun ParentScreen(
parentViewModel: ParentViewModel = hiltViewModel()
) {
val parentData by parentViewModel.parentData.collectAsState()
ChildWidget(parentData = parentData)
}
Run Code Online (Sandbox Code Playgroud)
在可组合项内部ParentScreen,我有一个ChildWidget可组合项,它有自己的ViewModel命名ChildViewModel.
@HiltViewModel
class ChildViewModel @AssistedInject constructor(
@Assisted val parentData: String
) : ViewModel() {
@AssistedFactory
interface ChildViewModelFactory {
fun create(parentData: String): ChildViewModel
}
init {
Timber.d("Child says data is $parentData ")
}
}
@Composable
fun ChildWidget(
parentData: String,
childViewModel: ChildViewModel = hiltViewModel() // How do I supply assisted injection factory here?
) {
// Code omitted
}
Run Code Online (Sandbox Code Playgroud)
现在,我想parentData进入ChildViewModel的构造函数。
问题
ChildViewModelFactory给 Navigation Compose 的hiltViewModel方法?ViewModel?lateinit创建如下所示的属性和方法怎么样init?@HiltViewModel
class ChildViewModel @Inject constructor(
) : ViewModel() {
lateinit var parentData: Long
fun init(parentData: Long){
if(this::parentData.isInitialized) return
this.parentData = parentData
}
}
Run Code Online (Sandbox Code Playgroud)
您可以使用EntryPointAccessors(来自 Hilt)和ViewModelProvider.Factory视图模型库来完成此操作。
在我的示例应用程序中,BookFormScreen正在使用BookFormViewModel,视图模型需要根据前一个屏幕传递的内容加载一本书bookId。这就是我所做的:
class BookFormViewModel @AssistedInject constructor(
...
@Assisted private val bookId: String?,
) : ViewModel() {
...
@AssistedFactory
interface Factory {
fun create(bookId: String?): BookFormViewModel
}
companion object {
@Suppress("UNCHECKED_CAST")
fun provideFactory(
assistedFactory: Factory, // this is the Factory interface
// declared above
bookId: String?
): ViewModelProvider.Factory = object : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return assistedFactory.create(bookId) as T
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,我没有使用@HiltViewModel. 将provideFactory用于提供工厂来创建此视图模型。
然后,定义ViewModelFactoryProvider入口点:
@EntryPoint
@InstallIn(ActivityComponent::class)
interface ViewModelFactoryProvider {
fun bookDetailsViewModelFactory(): BookDetailsViewModel.Factory
fun bookFormViewModelFactory(): BookFormViewModel.Factory
}
Run Code Online (Sandbox Code Playgroud)
现在,您需要定义一个可组合函数来使用此工厂提供视图模型。
@Composable
fun bookFormViewModel(bookId: String?): BookFormViewModel {
val factory = EntryPointAccessors.fromActivity(
LocalContext.current as Activity,
ViewModelFactoryProvider::class.java
).bookFormViewModelFactory()
return viewModel(factory = BookFormViewModel.provideFactory(factory, bookId))
}
Run Code Online (Sandbox Code Playgroud)
如果您使用导航库,您可以ViewModelStoreOwner在此函数中添加参数并在viewModel()函数调用中使用它。对于此参数,您可以传递NavBackStackEntry对象,这样视图模型的作用域将限于该特定的返回堆栈条目。
最后,您可以在可组合项中使用视图模型。
val bookFormViewModel: BookFormViewModel = bookFormViewModel(bookId)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2257 次 |
| 最近记录: |