如何在Java代码中初始化并调用Kotlin ViewModel?
在Java Activity中初始化并调用Kotlin编写的Hilt ViewModel
1. 配置Activity的Hilt支持
Java Activity必须添加@AndroidEntryPoint注解,让Hilt能够为其提供依赖注入能力:
@AndroidEntryPoint public class YourActivity extends AppCompatActivity { // Activity逻辑代码 }
2. 初始化ViewModel实例
在Activity的onCreate方法中,通过ViewModelProvider获取ViewModel实例(Hilt会自动适配Factory):
private PermProdsTestViewModel viewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.your_activity_layout); // 初始化ViewModel viewModel = new ViewModelProvider(this).get(PermProdsTestViewModel.class); }
3. 适配StateFlow的Java观察方案
Kotlin的StateFlow无法直接在Java中用协程collect,推荐转换为LiveData来观察,更符合Java开发习惯:
方案一:在ViewModel中新增LiveData属性(推荐)
修改Kotlin ViewModel,添加基于StateFlow的LiveData,供Java直接调用:
@HiltViewModel class PermProdsTestViewModel @Inject constructor( private val prodsUseCase: ProductUseCase // 注意:原代码方法内的permittedProdsUseCase是笔误,需统一为prodsUseCase ) : ViewModel() { private val _prods = MutableStateFlow(ProdsState()) val prods: StateFlow<ProdsState> = _prods // 新增:转换为LiveData供Java调用 val prodsLiveData: LiveData<ProdsState> = prods.asLiveData(viewModelScope.coroutineContext) fun getPermittedProducts(serviceName: String?, productTypes: List<String>?, permission: String?, subServiceName: String?, filter: Boolean?) = viewModelScope.launch(Dispatchers.IO) { prodsUseCase.invoke(serviceName, productTypes, permission, subServiceName, filter).collect() { when (it) { is DataResult.Success -> { _prods.value = ProdsState(products = it.data) Timber.d("Api request success, getting results") } is DataResult.Error -> { // 原代码未将错误状态赋值给_prods,此处修正 _prods.value = ProdsState(error = it.cause.localizedMessage ?: "Unexpected Error") Timber.d("Error getting permitted products") } } } } }
方案二:在Java中直接转换
如果不想修改ViewModel,可借助FlowKt工具类在Java中完成转换(需依赖androidx.lifecycle:lifecycle-runtime-ktx):
LiveData<ProdsState> prodsLiveData = FlowKt.asLiveData(viewModel.getProds(), Dispatchers.getMain());
然后在Activity中观察LiveData:
prodsLiveData.observe(this, prodsState -> { if (prodsState.getProducts() != null) { // 处理成功获取的产品数据,更新UI } else if (prodsState.getError() != null) { // 处理错误提示 } });
4. 调用ViewModel的业务方法
直接调用getPermittedProducts方法,传入业务所需参数即可:
// 示例参数,根据实际业务场景传值 viewModel.getPermittedProducts( "user_service", Arrays.asList("physical", "digital"), "view_permission", "sub_service_01", true );
关键注意事项
- 修正笔误:原ViewModel构造函数注入的是
prodsUseCase,但方法内误用了permittedProdsUseCase,需统一变量名,否则会触发未定义错误。 - 修正错误状态更新:原代码Error分支仅创建了
ProdsState但未赋值给_prods,导致UI无法感知错误状态,已在示例中修正。 - 依赖确认:确保项目已添加Hilt、ViewModel、LiveData相关依赖,避免运行时找不到类。
内容的提问来源于stack exchange,提问作者Pointyhat
相关产品推荐
相关产品推荐

