侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1823 篇文章
  • 累计收到 0 条评论

Android中如何安全使用协程处理网络请求并防止内存泄漏

2025-12-6 / 0 评论 / 4 阅读

题目

Android中如何安全使用协程处理网络请求并防止内存泄漏

信息

  • 类型:问答
  • 难度:⭐⭐

考点

Kotlin协程, Android生命周期感知, 内存泄漏防范

快速回答

在Android中使用协程处理网络请求时,需注意:

  • 使用viewModelScopelifecycleScope自动管理生命周期
  • 避免在Activity/Fragment中直接启动协程
  • 使用coroutineScopesupervisorScope处理异常
  • 通过viewModelScope.launch启动协程,ViewModel销毁时自动取消
## 解析

核心问题

在Android中直接启动协程处理网络请求可能导致:

  • 组件销毁后协程继续运行引发内存泄漏
  • 组件重建时产生僵尸协程
  • 异常未捕获导致应用崩溃

解决方案与代码示例

1. 使用ViewModel作用域

class MyViewModel : ViewModel() {
    fun fetchData() {
        viewModelScope.launch {
            try {
                val data = withContext(Dispatchers.IO) {
                    repository.getData() // 模拟网络请求
                }
                _dataLiveData.value = data
            } catch (e: Exception) {
                // 处理异常
            }
        }
    }
}

2. Fragment中使用lifecycleScope

class MyFragment : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        lifecycleScope.launchWhenStarted {
            try {
                val result = withContext(Dispatchers.IO) {
                    apiService.fetchData()
                }
                updateUI(result)
            } catch (e: Exception) {
                showError(e)
            }
        }
    }
}

最佳实践

  • 作用域选择
    • 业务逻辑使用viewModelScope
    • UI相关操作使用lifecycleScope
  • 线程调度
    • 网络请求使用Dispatchers.IO
    • UI更新使用Dispatchers.Main
  • 异常处理
    • 使用try/catch捕获具体异常
    • 使用CoroutineExceptionHandler全局处理

常见错误

  • 错误1:在Activity中直接启动协程
    // 危险!可能内存泄漏
    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            GlobalScope.launch {  // 错误示范
                val data = fetchData()
                runOnUiThread { updateUI(data) }
            }
        }
    }
  • 错误2:忽略协程取消
    viewModelScope.launch {
        val job = async(Dispatchers.IO) { heavyTask() }
        // 忘记检查isActive状态
        job.await()  // 即使ViewModel销毁仍会等待
    }

原理说明

  • 生命周期绑定viewModelScopeViewModel.onCleared()时自动取消所有子协程
  • 结构化并发:协程作用域形成父子关系,父作用域取消时自动传播到子协程
  • 内存安全:通过生命周期感知组件避免持有已销毁Activity的引用

扩展知识

  • 状态恢复:使用SavedStateHandle保存协程结果
  • 复杂流程
    • 使用flow处理数据流
    • 结合LiveData使用liveData { }构建器
  • 性能优化
    • 使用async并行请求
    • 通过coroutineScope创建子作用域
// 并行请求示例
viewModelScope.launch {
    coroutineScope {
        val userDeferred = async { getUserData() }
        val newsDeferred = async { getNewsFeed() }

        val user = userDeferred.await()
        val news = newsDeferred.await()

        mergeData(user, news)
    }
}