如何在HorizontalPager中向hiltViewModel()传递参数?
在HorizontalPager中为每个页面创建独立的Hilt ViewModel实例
要实现HorizontalPager每个页面拥有独立的PageViewModel实例并传入页面ID,核心是为每个页面提供独立的ViewModelStoreOwner,同时将ID注入到ViewModel的SavedStateHandle中,具体实现如下:
1. 为每个Pager页面创建独立的ViewModelStoreOwner
在ListScreen的HorizontalPager中,为每个页面绑定唯一的ViewModelStoreOwner,确保不同页面的ViewModel实例相互隔离:
@Composable fun ListScreen(viewModel: ListViewModel = hiltViewModel()) { val myIds: List<Int> by viewModel.ids.collectAsState(emptyList()) HorizontalPager( pageCount = myIds.size, ) { index -> val pageId = myIds[index] // 基于pageId创建独立的ViewModelStoreOwner,页面切换时自动复用/销毁 val pageViewModelStoreOwner = remember(pageId) { object : ViewModelStoreOwner { private val store = ViewModelStore() override val viewModelStore: ViewModelStore get() = store } } PageScreen(pageId, pageViewModelStoreOwner) } }
2. 在PageScreen中注入ID到ViewModel的SavedStateHandle
修改PageScreen,通过hiltViewModel的creationCallback将页面ID存入SavedStateHandle,同时指定独立的ViewModelStoreOwner:
@Composable fun PageScreen( id: Int, viewModelStoreOwner: ViewModelStoreOwner, viewModel: PageViewModel = hiltViewModel( viewModelStoreOwner = viewModelStoreOwner, creationCallback = { factory -> val savedStateHandle = SavedStateHandle().apply { set("page_id", id) } factory.create(PageViewModel::class.java, savedStateHandle) } ) ) { // 页面逻辑,可直接使用viewModel中的pageId }
3. 在PageViewModel中获取页面ID
从SavedStateHandle中取出传入的ID,用于后续业务逻辑:
@HiltViewModel class PageViewModel @Inject constructor( val savedStateHandle: SavedStateHandle ): ViewModel() { // 从SavedStateHandle获取页面ID,非空校验确保业务安全 val pageId: Int = checkNotNull(savedStateHandle["page_id"]) // 业务逻辑示例:根据pageId加载对应数据 // val pageData = flow { ... } }
关键说明
- 独立的ViewModelStoreOwner确保每个页面的ViewModel实例完全隔离,不会因Pager页面复用而共享状态。
- 使用
remember(pageId)绑定ViewModelStoreOwner的生命周期,当页面滑出屏幕超过offscreenLimit时,对应的ViewModel会自动销毁,符合Compose的生命周期管理。 - 通过SavedStateHandle传递ID,遵循Hilt ViewModel的设计规范,同时支持状态持久化(如配置变更时保留ID)。
内容的提问来源于stack exchange,提问作者Maydyk
相关产品推荐
相关产品推荐

