Hilt - HiltViewModel對Compose的Pager的支持

Pager一般需要使用不同參數(shù)的同類型的ViewModel,使用hiltViewModel無法創(chuàng)建實例(hilt未提供帶key實例化的方法),在不使用Hilt的情況下,viewModel是提供帶key的方法的。

背景

最近在研究Hilt如何與Compose進行工作協(xié)作,發(fā)現(xiàn)有一個問題。viewModel方法提供了帶key工作的方法,而hiltViewModel則沒有這樣的方法,這是十分不方便的。因為開發(fā)中,我們會經(jīng)常遇到使用Pager的情況,而Pager中的子頁面,使用的ViewModel往往是一個類型的帶不同參。這樣,hiltViewModel就無法適應這種情況,會出現(xiàn)幾個子頁面數(shù)據(jù)一模一樣的問題。經(jīng)過我不斷的搜查網(wǎng)絡上的資料,看到的有一個使用CompositionLocalProvider來提供幾個子頁面的ViewModelProviderOwner。但是這種方法會在hiltViewModel實例化你的PagerItemViewModel時報錯無法實例化。

網(wǎng)上給出的??是這樣的:

@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() //子視圖
            }
        }
}

以上代碼會出現(xiàn)報錯,因為hiltViewModel無法初始化完成,無法創(chuàng)建ViewModel的實例。因為ViewModelProviderOwner不是StackNavEntry,hiltViewModel無法正常工作。

解決方案

經(jīng)常嘗試且失敗后,我又查閱了很多資料,最終在bing國際版上發(fā)現(xiàn)compose官方的issue 里面有很多人同樣遇到這樣的問題且無法解決,找到官方看有什么方案提供。后來官方,給出了一個方案代碼,如下:

/**
 * 實例化帶參數(shù)Key的HiltViewModel對象,[issue地址](https://github.com/google/dagger/issues/2328)
 * @param key 參數(shù)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版本,可以先用以上代碼提供支持。

  • 如果能幫到你,請給我點個贊支持一下,謝謝!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容