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

Jetpack Compose 返回页面时如何重新调用ViewModel中的API更新数据

实现方案

问题根因

  • ViewModel的init代码块仅会在ViewModel实例第一次创建时执行一次,只要ViewModel绑定的宿主(如Activity、导航回栈条目)未销毁,导航返回时ViewModel不会重建,因此不会重新触发接口请求。

实现方案

我们可以通过在Compose页面监听生命周期可见事件,每次页面回到前台时主动触发接口调用:

第一步:修改Compose页面代码

在你的页面代码最上方添加如下生命周期监听逻辑:

import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.rememberUpdatedState

// 你的页面Composable函数
@Composable
fun ProfilePage(viewModel: ProfileViewModel = hiltViewModel()) {
    val lifecycleOwner = LocalLifecycleOwner.current
    val currentVm = rememberUpdatedState(newValue = viewModel)

    // 监听页面生命周期
    DisposableEffect(lifecycleOwner) {
        val observer = LifecycleEventObserver { _, event ->
            // 页面回到前台可见时触发接口请求
            if (event == Lifecycle.Event.ON_RESUME) {
                currentVm.value.clientInfoOnEvent()
            }
        }
        lifecycleOwner.lifecycle.addObserver(observer)
        onDispose {
            lifecycleOwner.lifecycle.removeObserver(observer)
        }
    }

    // 保留你原来的页面代码
    val state = viewModel.state.value
    Column(
        modifier = Modifier.fillMaxWidth(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.Start
    ) {
        // 原有逻辑不变
        state.info?.apply {
            Text(
                text = "$givenName $lastName",
                style = AppFont.PoppinsTypography.button,
                color = AppColor.neutralColor.CHARCOAL,
                modifier = Modifier.padding(top = 4.dp, bottom = 4.dp)
            )
            val clientData = let {
                it.copy(currency = Currency().copy(signSvg = it.currency?.signSvg.urlEncoder()))
            }
            TextIcon(
                text = stringResource(R.string.edit_profile),
                icon = painterResource(id = R.drawable.ic_right),
                color = AppColor.neutralColor.SPANISH_GRAY,
                style = AppFont.PoppinsTypography.caption,
                onCLick = {
                    state.info?.let {
                        viewModel.navigate(
                            EditProfileDestination.createEditProfileRoute(
                                Gson().toJson(clientData)
                            )
                        )
                    }
                })
        }
    }
}

第二步:可选优化

  1. 避免重复请求:你可以去掉ViewModel init块中的clientInfoOnEvent()调用,改为完全由生命周期ON_RESUME触发,第一次打开页面时也会自动调用,不会出现首次无数据的问题。
  2. 添加防抖逻辑:避免短时间内多次切页导致重复请求,同时修复原有代码未重置加载状态的问题,修改ViewModel代码:
@HiltViewModel
class ProfileViewModel @Inject constructor(
    private val profileUseCases: ProfileUseCases,
    private val clientNavigator: ClientNavigator,
    private val isLoggedInDataStore: IsLoggedInDataStore
) : ViewModel(), ClientNavigator by clientNavigator {

    private val _state = mutableStateOf(ProfileState())
    val state: State<ProfileState> = _state
    // 记录上次请求时间,用于防抖
    private var lastRequestTime = 0L

    // 可删除init块的调用,完全由生命周期触发
    // init {
    //     clientInfoOnEvent()
    // }

    fun clientInfoOnEvent() {
        // 1秒内只允许触发一次请求
        val currentTime = System.currentTimeMillis()
        if (currentTime - lastRequestTime < 1000) return
        lastRequestTime = currentTime

        profileUseCases.getClientInfoUseCase().onEach { result ->
            when (result) {
                is Resource.Success -> {
                    _state.value = state.value.copy(
                        info = result.data,
                        isLoading = false // 重置加载状态
                    )
                }
                is Resource.Error -> {
                    _state.value = state.value.copy(
                        error = result.message ?: "An unexpected error occurred",
                        isLoading = false // 重置加载状态
                    )
                }
                is Resource.Loading -> {
                    _state.value = state.value.copy(isLoading = true)
                }
            }
        }.launchIn(viewModelScope)
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 01:15:03