Android 协程全景式深度解析:第二章 结构化并发全解

2.1 作用域使用场景与最佳实践

2.1.1 Android作用域体系全景

作用域选择指南:

  • Activity/FragmentlifecycleScope(自动取消)
  • ViewModelviewModelScope(安全访问UI状态)
  • 全局后台任务 :自定义作用域(非GlobalScope
  • 跨组件任务Application作用域(谨慎使用)

2.1.2 ViewModel作用域源码解析

kotlin 复制代码
// ViewModel.kt 扩展属性
val ViewModel.viewModelScope: CoroutineScope
    get() {
        val scope: CoroutineScope? = this.getTag(JOB_KEY)
        if (scope != null) {
            return scope
        }
        return setTagIfAbsent(
            JOB_KEY,
            CloseableCoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
        )
    }

// 关闭逻辑
internal class CloseableCoroutineScope(
    context: CoroutineContext
) : Closeable, CoroutineScope {
    override val coroutineContext: CoroutineContext = context
    
    override fun close() {
        coroutineContext.cancel()
    }
}

// ViewModel清除时触发
override fun onCleared() {
    super.onCleared()
    (viewModelScope as CloseableCoroutineScope).close()
}

关键设计:

  1. 延迟初始化:首次访问时创建作用域
  2. SupervisorJob:子协程异常不会影响父级
  3. Main.immediate:立即执行主线程任务
  4. 自动取消:ViewModel销毁时清理所有协程

2.1.3 自定义作用域实现

kotlin 复制代码
class AppCoroutineScope : CoroutineScope {
    // 使用SupervisorJob防止单点失败
    private val job = SupervisorJob()
    
    // 自定义线程池
    private val dispatcher = Executors.newFixedThreadPool(4).asCoroutineDispatcher()
    
    override val coroutineContext: CoroutineContext
        get() = job + dispatcher + CoroutineName("app-scope") + CoroutineExceptionHandler { _, e ->
            logError("Scope error", e)
        }
    
    fun release() {
        job.cancel("App scope released")
        (dispatcher.executor as? ExecutorService)?.shutdown()
    }
}

// Application中使用
class MyApp : Application() {
    val appScope = AppCoroutineScope()
    
    override fun onTerminate() {
        super.onTerminate()
        appScope.release()
    }
}

2.2 Job树形结构与父子关系

2.2.1 Job状态机模型

2.2.2 父子关系源码实现

kotlin 复制代码
// JobSupport.kt#L1200
private fun addChildInternal(child: ChildHandleNode) {
    loop@ while (true) {
        val state = this.state
        when (state) {
            is Empty -> {
                // 初始化状态
                if (updateState(state, ChildList(child))) 
                    break@loop
            }
            is ChildList -> {
                // 添加子节点到链表
                val newList = state.list.addChild(child)
                if (updateState(state, newList)) 
                    break@loop
            }
            is Finishing -> {
                // 正在结束状态,通知子Job取消
                child.parentCancelled(state.rootCause)
                break@loop
            }
            else -> {
                // 已完成状态,子Job直接取消
                child.parentCancelled((state as? CompletedExceptionally)?.cause)
                break@loop
            }
        }
    }
}

// 原子更新状态
private fun updateState(expect: Any?, update: Any?): Boolean {
    return _state.compareAndSet(expect, update)
}

父子关系关键点:

  1. 原子操作:CAS保证线程安全
  2. 链表结构ChildList维护子Job链表
  3. 状态传播:父Job取消时遍历通知所有子Job
  4. 异常传递 :子Job异常通过ChildHandle上报

2.2.3 结构化并发优势

scss 复制代码
// 非结构化并发(危险!)
fun startTasks() {
    // 任务1:无关联
    GlobalScope.launch { task1() }
    
    // 任务2:无关联
    launch(Job()) { task2() } // 独立的Job
    
    // 问题:无法统一取消,可能导致泄漏
}

// 结构化并发(推荐)
fun startSafeTasks() {
    coroutineScope {
        launch { task1() } // 子协程1
        launch { task2() } // 子协程2
        
        // 所有子任务完成后才会继续
    }
    // 作用域外自动取消所有子任务
}

结构化优势对比表:

特性 非结构化 结构化
取消传播 ❌ 手动管理 ✅ 自动传播
异常处理 ❌ 容易丢失 ✅ 统一处理
生命周期 ❌ 容易泄漏 ✅ 自动绑定
代码可读性 ❌ 分散管理 ✅ 逻辑集中

2.3 取消与异常传播机制

2.3.1 取消操作全流程

2.3.2 协作式取消实现

kotlin 复制代码
// 可取消任务示例
suspend fun processLargeFile() {
    val inputStream = FileInputStream("largefile.bin")
    
    try {
        val buffer = ByteArray(8192)
        while (isActive) { // 检查活动状态
            val bytesRead = withContext(Dispatchers.IO) {
                inputStream.read(buffer)
            }
            if (bytesRead <= 0) break
            
            // 处理数据...
        }
    } finally {
        withContext(NonCancellable) {
            inputStream.close() // 确保资源关闭
            log("Stream closed safely")
        }
    }
}

// ViewModel中使用
fun startProcessing() {
    viewModelScope.launch {
        val job = launch { processLargeFile() }
        
        // 5秒后取消
        delay(5000)
        job.cancel("Timeout exceeded")
    }
}

2.3.3 异常传播机制源码

kotlin 复制代码
// JobSupport.kt#L1400
private fun handleJobException(exception: Throwable): Boolean {
    // 1. 尝试通过处理器处理
    val handled = handleException(exception)
    
    // 2. 未处理则传播给父Job
    if (!handled) {
        parent?.handleChildException(exception)?.let { return it }
    }
    
    // 3. 全局处理
    if (!handled) {
        handleUncaughtException(exception)
    }
    
    return true
}

// SupervisorJob的特殊处理
override fun handleChildException(exception: Throwable): Boolean {
    // 不传播给父级
    return false
}

异常传播路径:

  1. 当前Job的异常处理器
  2. 父Job的handleChildException
  3. 当前线程的未捕获异常处理器
  4. 全局CoroutineExceptionHandler

2.4 Android生命周期整合

2.4.1 lifecycleScope深度解析

kotlin 复制代码
// LifecycleController.kt
internal class LifecycleController(
    private val lifecycle: Lifecycle,
    private val minState: State,
    private val dispatchQueue: DispatchQueue
) {
    private val observer = LifecycleEventObserver { _, event ->
        if (event == Lifecycle.Event.ON_DESTROY) {
            // 销毁时取消所有协程
            handleDestroy()
        }
    }
    
    init {
        // 安全注册观察者
        if (lifecycle.currentState == Lifecycle.State.DESTROYED) {
            handleDestroy()
        } else {
            lifecycle.addObserver(observer)
        }
    }
    
    private fun handleDestroy() {
        dispatchQueue.cancel()
        lifecycle.removeObserver(observer)
    }
}

核心流程:

  1. 创建时绑定生命周期观察者
  2. ON_DESTROY事件触发作用域取消
  3. 移除观察者防止内存泄漏

2.4.2 生命周期感知协程构建器

kotlin 复制代码
// 自定义lifecycleScope扩展
fun LifecycleOwner.launchWhenCreated(
    block: suspend CoroutineScope.() -> Unit
): Job = lifecycleScope.launch {
    // 等待ON_CREATE状态
    lifecycle.whenCreated(block)
}

// 状态等待实现
suspend fun Lifecycle.whenCreated(block: suspend CoroutineScope.() -> Unit) {
    if (currentState >= Lifecycle.State.CREATED) {
        block()
    } else {
        // 挂起等待目标状态
        suspendCancellableCoroutine { cont ->
            val observer = object : LifecycleEventObserver {
                override fun onStateChanged(source: LifecycleOwner, event: Event) {
                    if (event == Event.ON_CREATE) {
                        source.lifecycle.removeObserver(this)
                        cont.resume(Unit)
                    } else if (event == Event.ON_DESTROY) {
                        cont.cancel("Lifecycle destroyed before reaching CREATED")
                    }
                }
            }
            addObserver(observer)
            cont.invokeOnCancellation { removeObserver(observer) }
        }
        block()
    }
}

2.5 全局异常处理策略

2.5.1 异常处理器金字塔

2.5.2 实现崩溃监控系统

kotlin 复制代码
class CrashMonitor : CoroutineExceptionHandler {
    override val key = CoroutineExceptionHandler
    
    override fun handleException(context: CoroutineContext, exception: Throwable) {
        // 1. 记录崩溃信息
        val job = context[Job]?.let { "Job: ${it.key}" } ?: "Unknown job"
        val coroutineName = context[CoroutineName]?.name ?: "unnamed"
        
        // 2. 上报到服务器
        FirebaseCrashlytics.getInstance().apply {
            log("Coroutine crash in $coroutineName ($job)")
            recordException(exception)
        }
        
        // 3. 主线程展示用户提示
        Handler(Looper.getMainLooper()).post {
            Toast.makeText(appContext, "操作失败,请重试", Toast.LENGTH_SHORT).show()
        }
    }
}

// 全局安装
class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        // 设置全局处理器
        Thread.setDefaultUncaughtExceptionHandler { thread, ex ->
            if (ex is CompletionHandlerException) {
                // 处理未捕获的协程异常
                CrashMonitor().handleException(EmptyCoroutineContext, ex.cause!!)
            } else {
                // 处理普通线程异常
                FirebaseCrashlytics.getInstance().recordException(ex)
            }
        }
    }
}

// 在作用域中使用
viewModelScope.launch(CrashMonitor()) {
    // 可能抛出异常的操作
}

本章小结

本章深入解析了结构化并发的核心机制:

  1. 作用域体系 :从ViewModelScope到自定义作用域
  2. Job树结构:父子关系与状态传播源码实现
  3. 取消机制:协作式取消与资源清理
  4. 异常传播:从子协程到全局处理器的完整路径
  5. 生命周期集成:Android特有的作用域绑定

在下一章中,我们将深入探讨Channel的内部实现机制,包括无锁队列设计、通道类型差异以及Select表达式的底层原理,揭示协程间通信的高效实现方式。

相关推荐
hsx6669 分钟前
使用 MaterialShapeDrawable 自定义各种形状的 View
android
用户2018792831671 小时前
滑动城堡的奇妙管家 ——ViewPager故事
android
用户2018792831671 小时前
📜 童话:魔法卷轴与 ScrollView 的奥秘
android
??? Meggie2 小时前
【SQL】使用UPDATE修改表字段的时候,遇到1054 或者1064的问题怎么办?
android·数据库·sql
用户2018792831672 小时前
代码共享法宝之maven-publish
android
yjm2 小时前
从一例 Lottie OOM 线上事故读源码
android·app
用户2018792831672 小时前
浅谈View的滑动
android
用户2018792831674 小时前
舞台剧兼职演员Dialog
android
参宿四南河三4 小时前
从Android实际应用场景出发,讲述RxJava3的简单使用
android·rxjava
扶我起来还能学_4 小时前
uniapp Android&iOS 定位权限检查
android·javascript·ios·前端框架·uni-app