Jetpack Compose中通过Hilt为Glance Widget注入ViewModel
解决Glance Widget中注入Hilt ViewModel的问题
由于Glance Widget的运行环境没有ViewModelStoreOwner(如Activity/Fragment这类组件),直接使用hiltViewModel()会失效,以下是可行的实现方案:
步骤1:为Widget Receiver添加Hilt注解
给CustomGlanceWidgetReceiver加上@AndroidEntryPoint,让Hilt能够管理其依赖注入:
@AndroidEntryPoint class CustomGlanceWidgetReceiver : GlanceAppWidgetReceiver() { override val glanceAppWidget: GlanceAppWidget = MyAppWidget() }
步骤2:定义Hilt EntryPoint获取ViewModel工厂
创建一个EntryPoint接口,用于从Hilt的单例组件中获取ViewModel的创建工厂:
@EntryPoint @InstallIn(SingletonComponent::class) interface ViewModelFactoryEntryPoint { fun viewModelFactory(): ViewModelProvider.Factory }
步骤3:在Widget中创建ViewModel实例
在MyAppWidget的provideGlance方法中,通过Hilt EntryPoint获取ViewModel工厂,手动创建ViewModel实例(临时实现ViewModelStoreOwner来满足ViewModelProvider的要求):
class MyAppWidget : GlanceAppWidget() { override suspend fun provideGlance(context: Context, id: GlanceId) { // 从Application Context获取Hilt EntryPoint val entryPoint = EntryPointAccessors.fromApplication( context.applicationContext, ViewModelFactoryEntryPoint::class.java ) val viewModelFactory = entryPoint.viewModelFactory() // 创建ViewModel实例 val viewModel = ViewModelProvider( object : ViewModelStoreOwner { private val store = ViewModelStore() override fun getViewModelStore(): ViewModelStore = store }, viewModelFactory )[BaseEntryWidgetViewModel::class.java] provideContent { MyContent(viewModel) } } }
步骤4:在Glance Composable中使用ViewModel
修改MyContent,直接接收传入的ViewModel实例并调用其方法:
@Composable private fun MyContent( viewModel: BaseEntryWidgetViewModel ) { Column( modifier = GlanceModifier.fillMaxSize(), verticalAlignment = Alignment.Top, horizontalAlignment = Alignment.CenterHorizontally ) { Row(horizontalAlignment = Alignment.CenterHorizontally) { TextField(value = "", onValueChange = {}, label = { Text(text = "Title") }) TextField(value = "", onValueChange = {}, label = { Text(text = "Amount") }) Button( text = "Save", onClick = { // 调用ViewModel的业务方法 // viewModel.saveEntry(...) } ) Button( text = "Work", onClick = { // viewModel.doWork() } ) } } }
注意事项
- 每次Widget更新时
provideGlance都会被调用,ViewModel实例也会重新创建。如果需要持久化状态,建议将数据存储到Room、SharedPreferences等介质中。 - 确保你的Application类已添加
@HiltAndroidApp注解,这是Hilt工作的基础:
@HiltAndroidApp class MyApplication : Application()
内容的提问来源于stack exchange,提问作者geontricks developer
相关产品推荐
相关产品推荐

