Jetpack Compose应用启动后冻结问题排查求助
问题原因分析
你的应用启动后冻结30秒的核心原因是一次性并发发起8个网络请求,直接耗尽了IO线程池资源,进而阻塞了与UI相关的IO操作,最终导致UI线程无响应:
IO线程池被完全占满:
retry()方法里循环创建8个协程(对应8种排序组合),每个协程都在Dispatchers.IO执行网络请求。IO线程池默认大小为CPU核心数 × 2(比如4核设备就是8个线程),这8个请求直接占满所有IO线程,导致后续其他依赖IO线程的操作(比如数据库读写、UI相关的文件操作)完全阻塞,无法及时处理,最终让UI线程陷入等待,表现为应用冻结。激进的预加载逻辑:你一次性加载了所有8种排序组合的数据,但用户当前只会看到其中一种排序的内容,其余7种属于无必要的预加载,这种方式直接耗尽了系统资源。
协程作用域的潜在问题:
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
相关产品推荐
相关产品推荐

