You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 07:10:57