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

Jetpack Compose应用启动后冻结问题排查求助

问题原因分析

你的应用启动后冻结30秒的核心原因是一次性并发发起8个网络请求,直接耗尽了IO线程池资源,进而阻塞了与UI相关的IO操作,最终导致UI线程无响应:

  1. IO线程池被完全占满:retry()方法里循环创建8个协程(对应8种排序组合),每个协程都在Dispatchers.IO执行网络请求。IO线程池默认大小为CPU核心数 × 2(比如4核设备就是8个线程),这8个请求直接占满所有IO线程,导致后续其他依赖IO线程的操作(比如数据库读写、UI相关的文件操作)完全阻塞,无法及时处理,最终让UI线程陷入等待,表现为应用冻结。

  2. 激进的预加载逻辑:你一次性加载了所有8种排序组合的数据,但用户当前只会看到其中一种排序的内容,其余7种属于无必要的预加载,这种方式直接耗尽了系统资源。

  3. 协程作用域的潜在问题:getAssetModels()里使用CoroutineScope(Dispatchers.IO)创建独立协程作用域,该作用域与viewModelScope无关,可能导致协程泄漏,进一步加重资源消耗。

修复方案

1. 限制并发请求数量

用viewModelScope配合async+awaitAll,设置合理的并发数,避免一次性占满IO线程:

fun retry() {
    val params = listOf(
        Pair(SortedBy.PRICE, SortingType.ASC),
        Pair(SortedBy.PRICE, SortingType.DSC),
        Pair(SortedBy.VOLUME, SortingType.ASC),
        Pair(SortedBy.VOLUME, SortingType.DSC),
        Pair(SortedBy.GAINERS, SortingType.ASC),
        Pair(SortedBy.GAINERS, SortingType.DSC),
        Pair(SortedBy.MARKET_CAP, SortingType.ASC),
        Pair(SortedBy.MARKET_CAP, SortingType.DSC),
    )
    viewModelScope.launch(Dispatchers.IO) {
        // 限制每次并发2个请求,可根据设备性能调整
        params.chunked(2).forEach { chunk ->
            chunk.mapIndexed { index, param ->
                async {
                    val globalIndex = params.indexOf(param)
                    getAssetModels(param.first, param.second, _assetModels[globalIndex])
                }
            }.awaitAll()
        }
    }
}

2. 仅加载当前需要的数据

取消一次性预加载所有排序,只加载用户当前选中的排序数据,其余排序在用户切换时再触发加载:

// 在HomeViewModel中维护当前选中的排序参数
var currentSort by mutableStateOf(Pair(SortedBy.PRICE, SortingType.ASC))

fun retry() {
    // 仅加载当前选中的排序数据
    val index = params.indexOf(currentSort)
    getAssetModels(currentSort.first, currentSort.second, _assetModels[index])
}

// 用户切换排序时调用此方法
fun onSortSelected(sortPair: Pair<SortedBy, SortingType>) {
    currentSort = sortPair
    retry()
}

3. 统一协程作用域

将getAssetModels()中的自定义协程作用域替换为viewModelScope,避免协程泄漏:

fun getAssetModels(
    sortedBy: SortedBy, sortingType: com.example.ramzinium.data.SortingType,
    state: MutableStateFlow<PagingData<AssetModel>>,
) = viewModelScope.launch(Dispatchers.IO) {
    jwt?.let { UseCaseInput(it, sortedBy, sortingType) }?.let { input ->
        getAssetListUseCase.execute(input)
            .distinctUntilChanged()
            .cachedIn(viewModelScope)
            .collect {
                state.value = it
                _dataLoadedFromNetwork.update { true }
            }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 07:08:16