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

Kotlin Jetpack Compose首页API调用优化与加载指示器修复

优化多API调用逻辑并修复加载指示器问题

一、优化多API调用逻辑

1. 并发执行多个API请求

放弃串行调用oggetti和utenti接口,改用协程并发执行以减少总耗时。ViewModel中可通过async+awaitAll或Flow的combine操作符合并结果:

协程async实现并发:

class HomeViewModel(private val repository: HomeRepository) : ViewModel() {
    private val _uiState = MutableStateFlow<HomeUiState>(HomeUiState.Loading)
    val uiState: StateFlow<HomeUiState> = _uiState.asStateFlow()

    init {
        fetchData()
    }

    private fun fetchData() = viewModelScope.launch {
        val oggettiDeferred = async { repository.getOggetti() }
        val utentiDeferred = async { repository.getUtenti() }

        try {
            val oggetti = oggettiDeferred.await()
            val utenti = utentiDeferred.await()
            _uiState.value = HomeUiState.Success(oggetti, utenti)
        } catch (e: Exception) {
            _uiState.value = HomeUiState.Error(e.message ?: "加载失败")
        }
    }
}

// 定义统一UI状态密封类
sealed class HomeUiState {
    object Loading : HomeUiState()
    data class Success(val oggetti: List<Oggetto>, val utenti: List<Utente>) : HomeUiState()
    data class Error(val message: String) : HomeUiState()
}

Flow combine实现(适配实时更新场景):

class HomeViewModel(private val repository: HomeRepository) : ViewModel() {
    val uiState: StateFlow<HomeUiState> = combine(
        repository.getOggettiFlow(),
        repository.getUtentiFlow()
    ) { oggettiResult, utentiResult ->
        when {
            oggettiResult is Result.Loading || utentiResult is Result.Loading -> HomeUiState.Loading
            oggettiResult is Result.Success && utentiResult is Result.Success -> 
                HomeUiState.Success(oggettiResult.data, utentiResult.data)
            else -> HomeUiState.Error("部分数据加载失败")
        }
    }.stateIn(
        scope = viewModelScope,
        started = SharingStarted.WhileSubscribed(5000),
        initialValue = HomeUiState.Loading
    )
}

2. 增加本地缓存策略

用Room等工具对oggetti和utenti数据做本地缓存,首次加载后优先读取缓存,后台同步最新数据,提升重复打开页面的速度:

class HomeRepository(private val apiService: ApiService, private val dao: HomeDao) {
    suspend fun getOggetti(): List<Oggetto> {
        val cache = dao.getOggetti()
        return if (cache.isNotEmpty()) {
            viewModelScope.launch {
                val remoteData = apiService.getOggetti()
                dao.insertOggetti(remoteData)
            }
            cache
        } else {
            val remoteData = apiService.getOggetti()
            dao.insertOggetti(remoteData)
            remoteData
        }
    }
}

3. 后端API合并(若可行)

如果能协调后端,将oggetti和utenti接口合并为一个,减少网络请求次数,从根源降低加载耗时。

二、修复加载指示器异常问题

加载指示器提前结束的核心原因是未统一管理所有API请求的加载状态,之前的实现可能仅监听单个请求状态,导致某个请求完成就关闭加载,其他请求仍在进行。

1. 统一UI状态管理

使用上述HomeUiState密封类,仅当所有请求完成(成功/失败)时,才切换出Loading状态。

2. Compose中正确响应状态

在Compose页面根据uiState渲染UI,确保加载指示器在所有请求完成前持续显示:

@Composable
fun HomeScreen(viewModel: HomeViewModel = viewModel()) {
    val uiState by viewModel.uiState.collectAsStateWithLifecycle()

    when (uiState) {
        is HomeUiState.Loading -> {
            Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
                CircularProgressIndicator()
            }
        }
        is HomeUiState.Success -> {
            val state = uiState as HomeUiState.Success
            HomeContent(oggetti = state.oggetti, utenti = state.utenti)
        }
        is HomeUiState.Error -> {
            val errorMessage = (uiState as HomeUiState.Error).message
            Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
                Text(text = errorMessage)
            }
        }
    }
}

3. 规避局部状态错误

不要为每个API请求单独设置加载状态,必须用统一状态标识所有请求的整体加载情况,确保所有请求完成后才隐藏加载指示器。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 19:12:45