美文网首页
Hilt - HiltViewModel对Compose的Pag

Hilt - HiltViewModel对Compose的Pag

作者: Cosecant | 来源:发表于2023-09-01 17:08 被阅读0次

Pager一般需要使用不同参数的同类型的ViewModel,使用hiltViewModel无法创建实例(hilt未提供带key实例化的方法),在不使用Hilt的情况下,viewModel是提供带key的方法的。

背景

最近在研究Hilt如何与Compose进行工作协作,发现有一个问题。viewModel方法提供了带key工作的方法,而hiltViewModel则没有这样的方法,这是十分不方便的。因为开发中,我们会经常遇到使用Pager的情况,而Pager中的子页面,使用的ViewModel往往是一个类型的带不同参。这样,hiltViewModel就无法适应这种情况,会出现几个子页面数据一模一样的问题。经过我不断的搜查网络上的资料,看到的有一个使用CompositionLocalProvider来提供几个子页面的ViewModelProviderOwner。但是这种方法会在hiltViewModel实例化你的PagerItemViewModel时报错无法实例化。

网上给出的🌰是这样的:

@hiltViewModel
class PagerViewModel @Inject constructor() : ViewModel(){

    private var viewModelStores = mutableMapOf<Int, ViewModelStore>()

    fun getViewModelStoreOwner(page: Int): ViewModelStoreOwner {
        return object : ViewModelStoreOwner {
            override val viewModelStore: ViewModelStore
                get() {
                    var vms = viewModelStores[page]
                    if (vms == null) {
                        vms = ViewModelStore()
                        viewModelStores[page] = vms
                    }
                    return vms
                }
        }
    }
}

@Composable
fun PagerView(val mainViewModel:PagerViewModel = hiltViewModel()){
        HorizontalPager(
            modifier = Modifier
                .fillMaxSize(),
            state = pagerState,
        ) { page ->
            CompositionLocalProvider(LocalViewModelProviderOwner provides mainViewModel.getViewModelStoreOwner(page){
                    PagerItemView() //子视图
            }
        }
}

以上代码会出现报错,因为hiltViewModel无法初始化完成,无法创建ViewModel的实例。因为ViewModelProviderOwner不是StackNavEntry,hiltViewModel无法正常工作。

解决方案

经常尝试且失败后,我又查阅了很多资料,最终在bing国际版上发现compose官方的issue 里面有很多人同样遇到这样的问题且无法解决,找到官方看有什么方案提供。后来官方,给出了一个方案代码,如下:

/**
 * 实例化带参数Key的HiltViewModel对象,[issue地址](https://github.com/google/dagger/issues/2328)
 * @param key 参数key
 */
@Composable
inline fun <reified VM : ViewModel> hiltViewModel(key: String): VM {
    val viewModelStoreOwner =
        if (checkNotNull(LocalViewModelStoreOwner.current) is NavBackStackEntry) {
            checkNotNull(LocalViewModelStoreOwner.current) { "ViewModelStoreOwner is null" }
        } else null
    return viewModel(
        key = key,
        factory = if (viewModelStoreOwner is NavBackStackEntry) {
            HiltViewModelFactory(LocalContext.current, viewModelStoreOwner)
        } else null
    )
}

就这样,在Pager中使用hiltViewModel(key=name)方法完成ViewModel实例化。虽然官方提供了解决方案,但是在hilt-navigation:1.0.0版本中并不支持,1.1.0版本才开始支持,目前还是alpha版本,可以先用以上代码提供支持。

  • 如果能帮到你,请给我点个赞支持一下,谢谢!

相关文章

网友评论

      本文标题:Hilt - HiltViewModel对Compose的Pag

      本文链接:https://www.haomeiwen.com/subject/tmmtvdtx.html