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

Jetpack Compose NavHost二次重组导致MVVM+Hilt场景下请求重复调用问题求解

问题根源

  • 你定义的planeInfo()是普通成员方法,每次调用都会执行planeInfoUseCase.execute()生成新的Flow实例,再转为新的LiveData实例,每次新的LiveData被观察都会触发一次数据流启动
  • NavHost的composable代码块会随导航状态变化、宿主页面重组触发多次执行,每次执行都会调用PlanesScreen内的viewModel.planeInfo()生成新的LiveData,最终触发多次重复请求

修复方案

第一步:将数据流改为ViewModel成员变量,仅初始化一次

ViewModel的生命周期和页面绑定,只要页面未出栈销毁,ViewModel实例就不会重建,成员变量仅会初始化一次,从根源避免重复生成数据流:

@HiltViewModel
class PlanesViewModel @Inject constructor(private val planeInfoUseCase: PlaneInfoUseCase) : ViewModel() {
    // 改为成员变量,ViewModel实例化时仅执行一次数据请求
    val planeInfo: LiveData<UiResponse<ArrayList<PlaneInfo>>> = 
        planeInfoUseCase.execute().toUiResponse().flowAsLiveData(Dispatchers.IO)
}

第二步:调整PlanesScreen调用逻辑,直接访问成员变量

不需要再调用方法生成新的LiveData,直接观察固定的成员变量即可,同时可以直接在PlanesScreen内部获取Hilt注入的ViewModel,不需要上层传参:

@Composable
fun PlanesScreen(viewModel : PlanesViewModel = hiltViewModel()){
    PlaneList(viewModel.planeInfo.observeAsState())
}

第三步:简化Navigation层代码

不需要在NavHost的composable块中传入ViewModel,完全不需要把ViewModel往上透传给Navigation函数:

@Composable
fun Navigation(navController: NavHostController){
    NavHost(navController, startDestination = NavigationItem.Planes.route) {
        composable(NavigationItem.Planes.route) {
            // 无需传参,ViewModel在PlanesScreen内部获取
            PlanesScreen()
        }
        composable(NavigationItem.Weather.route) {
            WeatherScreen()
        }
        composable(NavigationItem.More.route) {
            MoreScreen()
        }
    }
}

可选优化(非必须)

你可以省去Flow转LiveData的环节,直接在Compose中通过collectAsStateWithLifecycle收集Flow数据,更适配Compose生命周期,性能表现更好:

// ViewModel中直接返回Flow
val planeInfo: Flow<UiResponse<ArrayList<PlaneInfo>>> = 
    planeInfoUseCase.execute().toUiResponse().flowOn(Dispatchers.IO)

// Compose中直接收集
@Composable
fun PlanesScreen(viewModel : PlanesViewModel = hiltViewModel()){
    val state by viewModel.planeInfo.collectAsStateWithLifecycle(initialValue = UiResponse.Loading())
    PlaneList(state)
}

内容的提问来源于stack exchange,提问作者Shindra

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 09:24:03