01-01-02 协程作用域与生命周期完全指南

目录


1. 协程作用域概念

1.1 什么是协程作用域

协程作用域(CoroutineScope)定义了协程的生命周期边界,管理协程的创建、取消和完成。

/**
 * 协程作用域基础
 */
class ScopeBasics {

    // 作用域的本质
    interface CoroutineScope {
        val coroutineContext: CoroutineContext
    }

    // 创建基础作用域
    fun createBasicScope() {
        val scope = CoroutineScope(Dispatchers.Main)

        scope.launch {
            println("Running in scope")
        }

        // 取消作用域
        scope.cancel()
    }

    // 作用域控制生命周期
    fun scopeLifecycle() = runBlocking {
        val scope = CoroutineScope(Job())

        scope.launch {
            repeat(5) {
                delay(500)
                println("Task $it")
            }
        }

        delay(1200)
        scope.cancel() // 取消所有协程
        println("Scope cancelled")
    }
}

1.2 作用域的作用

/**
 * 协程作用域的三大作用
 */
class ScopePurpose {

    // 1. 生命周期管理
    fun lifecycleManagement() {
        val scope = CoroutineScope(Job() + Dispatchers.Main)

        // 启动多个协程
        scope.launch { doWork1() }
        scope.launch { doWork2() }
        scope.launch { doWork3() }

        // 一次性全部取消
        scope.cancel()
    }

    // 2. 结构化并发
    suspend fun structuredConcurrency() = coroutineScope {
        launch { doWork1() }
        launch { doWork2() }
        // 等待所有子协程完成
    }

    // 3. 异常传播
    suspend fun exceptionPropagation() {
        try {
            coroutineScope {
                launch {
                    throw RuntimeException("Error")
                }
                launch {
                    delay(1000)
                    println("Won't execute")
                }
            }
        } catch (e: Exception) {
            println("Caught: ${e.message}")
        }
    }

    private suspend fun doWork1() { delay(100) }
    private suspend fun doWork2() { delay(100) }
    private suspend fun doWork3() { delay(100) }
}

1.3 作用域的层次结构

/**
 * 协程作用域的层次关系
 */
class ScopeHierarchy {

    fun demonstrateHierarchy() = runBlocking {
        println("Root")

        launch {
            println("  Parent")

            launch {
                println("    Child 1")

                launch {
                    println("      GrandChild")
                }
            }

            launch {
                println("    Child 2")
            }
        }
    }

    // 父协程等待所有子协程
    suspend fun parentWaitsChildren() = coroutineScope {
        launch {
            delay(1000)
            println("Child 1 done")
        }

        launch {
            delay(2000)
            println("Child 2 done")
        }

        println("Parent waiting...")
        // coroutineScope会等待所有子协程完成
    }

    // 父协程取消会取消所有子协程
    suspend fun parentCancelsChildren() = coroutineScope {
        val parent = launch {
            launch {
                try {
                    delay(Long.MAX_VALUE)
                } catch (e: CancellationException) {
                    println("Child 1 cancelled")
                }
            }

            launch {
                try {
                    delay(Long.MAX_VALUE)
                } catch (e: CancellationException) {
                    println("Child 2 cancelled")
                }
            }

            delay(1000)
        }

        delay(500)
        parent.cancel()
        println("Parent cancelled")
    }
}

2. GlobalScope

2.1 GlobalScope特点

/**
 * GlobalScope: 全局作用域
 *
 * 特点:
 * - 生命周期是整个应用进程
 * - 不会自动取消
 * - 不推荐使用
 */
class GlobalScopeExample {

    // 基础用法
    fun basicUsage() {
        GlobalScope.launch {
            delay(1000)
            println("Global coroutine")
        }
        // 应用关闭前协程一直运行
    }

    // 问题示例: 内存泄漏
    class LeakyActivity : AppCompatActivity() {

        private lateinit var textView: TextView

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)

            // ❌ 不推荐
            GlobalScope.launch {
                delay(10000)
                textView.text = "Updated" // Activity已销毁,崩溃!
            }
        }
    }

    // 合理使用场景: 应用级别的后台任务
    object AppLogger {
        private val logQueue = Channel<String>(Channel.UNLIMITED)

        init {
            GlobalScope.launch {
                for (log in logQueue) {
                    writeLogToFile(log)
                }
            }
        }

        fun log(message: String) {
            logQueue.trySend(message)
        }

        private suspend fun writeLogToFile(log: String) {
            withContext(Dispatchers.IO) {
                File("app.log").appendText("$log\n")
            }
        }
    }
}

2.2 为什么不推荐GlobalScope

/**
 * GlobalScope的问题
 */
class GlobalScopeProblems {

    // 问题1: 无法控制生命周期
    class ProblemActivity : AppCompatActivity() {

        fun loadData() {
            GlobalScope.launch {
                val data = fetchData() // 耗时操作
                updateUI(data) // Activity可能已销毁
            }
        }

        private suspend fun fetchData(): String {
            delay(5000)
            return "Data"
        }

        private fun updateUI(data: String) {
            // 可能崩溃或泄漏
        }
    }

    // 问题2: 难以测试
    class DataManager {
        fun loadData() {
            GlobalScope.launch {
                // 测试时无法等待完成
                processData()
            }
        }

        private suspend fun processData() {
            delay(1000)
        }
    }

    // 问题3: 资源泄漏
    class ResourceLeaker {
        private val resources = mutableListOf<Resource>()

        fun doWork() {
            GlobalScope.launch {
                val resource = acquireResource()
                resources.add(resource)
                // 如果没有清理,资源会一直占用
                delay(Long.MAX_VALUE)
            }
        }

        private fun acquireResource(): Resource = Resource()
    }

    class Resource
}

2.3 替代方案

/**
 * GlobalScope的替代方案
 */
class GlobalScopeAlternatives {

    // 方案1: 使用lifecycleScope
    class MyActivity : AppCompatActivity() {

        fun loadData() {
            lifecycleScope.launch {
                val data = fetchData()
                updateUI(data) // 安全,Activity销毁时自动取消
            }
        }

        private suspend fun fetchData(): String {
            delay(5000)
            return "Data"
        }

        private fun updateUI(data: String) {}
    }

    // 方案2: 使用viewModelScope
    class MyViewModel : ViewModel() {

        fun loadData() {
            viewModelScope.launch {
                // ViewModel清除时自动取消
                processData()
            }
        }

        private suspend fun processData() {
            delay(1000)
        }
    }

    // 方案3: 自定义应用级作用域
    object AppScope : CoroutineScope {
        private val job = SupervisorJob()
        override val coroutineContext = Dispatchers.Main + job

        fun cancelAll() {
            job.cancel()
        }
    }

    class AppLevelWork {
        fun doWork() {
            AppScope.launch {
                // 应用级任务
                processBackgroundData()
            }
        }

        private suspend fun processBackgroundData() {
            delay(1000)
        }
    }
}

3. lifecycleScope

3.1 lifecycleScope基础

/**
 * lifecycleScope: Activity/Fragment的生命周期作用域
 *
 * 自动绑定生命周期:
 * - Activity/Fragment销毁时自动取消
 * - 安全的UI更新
 */
class LifecycleScopeBasics : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // 基础用法
        lifecycleScope.launch {
            val data = fetchData()
            updateUI(data) // 安全,Activity销毁时协程被取消
        }

        // 并发任务
        lifecycleScope.launch {
            coroutineScope {
                val data1 = async { fetchData1() }
                val data2 = async { fetchData2() }
                val data3 = async { fetchData3() }

                displayResults(data1.await(), data2.await(), data3.await())
            }
        }
    }

    private suspend fun fetchData(): String {
        delay(1000)
        return "Data"
    }

    private suspend fun fetchData1(): String {
        delay(500)
        return "Data1"
    }

    private suspend fun fetchData2(): String {
        delay(500)
        return "Data2"
    }

    private suspend fun fetchData3(): String {
        delay(500)
        return "Data3"
    }

    private fun updateUI(data: String) {}
    private fun displayResults(d1: String, d2: String, d3: String) {}
}

3.2 生命周期感知

/**
 * lifecycleScope的生命周期感知特性
 */
class LifecycleAwareness : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // repeatOnLifecycle: 在指定生命周期状态重复执行
        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                // STARTED状态时执行
                // STOPPED状态时取消
                // STARTED状态时再次执行
                collectDataFlow()
            }
        }

        // launchWhenStarted: STARTED状态及以上时执行
        lifecycleScope.launchWhenStarted {
            // STARTED状态时开始
            // STOPPED状态时挂起(不是取消)
            // STARTED状态时继续
            updateUI()
        }

        // launchWhenResumed: RESUMED状态时执行
        lifecycleScope.launchWhenResumed {
            // RESUMED状态时执行
            // PAUSED状态时挂起
            startAnimation()
        }

        // launchWhenCreated: CREATED状态及以上时执行
        lifecycleScope.launchWhenCreated {
            // 几乎立即执行
            initializeData()
        }
    }

    private suspend fun collectDataFlow() {
        dataFlow.collect { data ->
            println("Received: $data")
        }
    }

    private suspend fun updateUI() {
        delay(1000)
    }

    private suspend fun startAnimation() {
        delay(1000)
    }

    private suspend fun initializeData() {
        delay(1000)
    }

    private val dataFlow: Flow<String> = flow {
        repeat(100) {
            delay(1000)
            emit("Data $it")
        }
    }
}

3.3 repeatOnLifecycle最佳实践

/**
 * repeatOnLifecycle: 推荐的Flow收集方式
 */
class RepeatOnLifecycleExample : AppCompatActivity() {

    private val viewModel: MyViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // ✅ 推荐: 使用repeatOnLifecycle
        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                viewModel.uiState.collect { state ->
                    updateUI(state)
                }
            }
        }

        // ❌ 不推荐: 直接在lifecycleScope.launch中收集
        // 问题: Activity在后台时仍然收集,浪费资源
        lifecycleScope.launch {
            viewModel.uiState.collect { state ->
                updateUI(state)
            }
        }

        // ✅ 收集多个Flow
        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                launch {
                    viewModel.uiState.collect { state ->
                        updateUI(state)
                    }
                }

                launch {
                    viewModel.events.collect { event ->
                        handleEvent(event)
                    }
                }

                launch {
                    viewModel.errors.collect { error ->
                        showError(error)
                    }
                }
            }
        }
    }

    private fun updateUI(state: UiState) {}
    private fun handleEvent(event: Event) {}
    private fun showError(error: String) {}
}

class MyViewModel : ViewModel() {
    val uiState = MutableStateFlow(UiState())
    val events = MutableSharedFlow<Event>()
    val errors = MutableSharedFlow<String>()
}

data class UiState(val loading: Boolean = false)
sealed class Event

3.4 Fragment中使用

/**
 * Fragment中的lifecycleScope
 */
class MyFragment : Fragment() {

    private var _binding: FragmentMyBinding? = null
    private val binding get() = _binding!!

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

        // ⚠️ 注意: Fragment有两个生命周期
        // 1. Fragment自己的生命周期
        // 2. Fragment View的生命周期

        // ✅ 推荐: 使用viewLifecycleOwner
        viewLifecycleOwner.lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                // View重建时会重新执行
                collectData()
            }
        }

        // ❌ 不推荐: 使用Fragment的lifecycleScope
        // 问题: Fragment被detach后协程仍在运行
        lifecycleScope.launch {
            collectData()
        }
    }

    private suspend fun collectData() {
        dataFlow.collect { data ->
            binding.textView.text = data
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }

    private val dataFlow: Flow<String> = flow {
        emit("Data")
    }
}

4. viewModelScope

4.1 viewModelScope基础

/**
 * viewModelScope: ViewModel的协程作用域
 *
 * 特点:
 * - ViewModel清除时自动取消
 * - 配置改变时不会取消
 * - 适合长生命周期任务
 */
class ViewModelScopeBasics : ViewModel() {

    private val _data = MutableStateFlow<String>("")
    val data: StateFlow<String> = _data.asStateFlow()

    private val _loading = MutableStateFlow(false)
    val loading: StateFlow<Boolean> = _loading.asStateFlow()

    private val _error = MutableSharedFlow<String>()
    val error: SharedFlow<String> = _error.asSharedFlow()

    // 基础用法
    fun loadData() {
        viewModelScope.launch {
            _loading.value = true
            try {
                val result = fetchData()
                _data.value = result
            } catch (e: Exception) {
                _error.emit("加载失败: ${e.message}")
            } finally {
                _loading.value = false
            }
        }
    }

    // 并发任务
    fun loadMultipleData() {
        viewModelScope.launch {
            _loading.value = true
            try {
                coroutineScope {
                    val data1 = async { fetchData1() }
                    val data2 = async { fetchData2() }
                    val data3 = async { fetchData3() }

                    val results = listOf(
                        data1.await(),
                        data2.await(),
                        data3.await()
                    )

                    _data.value = results.joinToString()
                }
            } catch (e: Exception) {
                _error.emit("加载失败: ${e.message}")
            } finally {
                _loading.value = false
            }
        }
    }

    // 后台任务
    fun startBackgroundSync() {
        viewModelScope.launch {
            while (isActive) {
                syncData()
                delay(60_000) // 每分钟同步一次
            }
        }
    }

    private suspend fun fetchData(): String {
        delay(1000)
        return "Data"
    }

    private suspend fun fetchData1(): String = "Data1"
    private suspend fun fetchData2(): String = "Data2"
    private suspend fun fetchData3(): String = "Data3"
    private suspend fun syncData() {}
}

4.2 配置改变时的行为

/**
 * viewModelScope在配置改变时的行为
 */
class ConfigChangeExample {

    // ViewModel
    class MyViewModel : ViewModel() {

        init {
            viewModelScope.launch {
                println("ViewModel coroutine started")
                repeat(10) {
                    delay(1000)
                    println("Tick $it")
                }
                println("ViewModel coroutine finished")
            }
        }

        override fun onCleared() {
            println("ViewModel cleared")
            super.onCleared()
        }
    }

    // Activity
    class MyActivity : AppCompatActivity() {

        private val viewModel: MyViewModel by viewModels()

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            println("Activity onCreate")

            // 旋转屏幕:
            // 1. Activity被销毁并重建
            // 2. ViewModel不会被清除
            // 3. viewModelScope中的协程继续运行

            // 按返回键:
            // 1. Activity被finish
            // 2. ViewModel被清除
            // 3. viewModelScope中的协程被取消
        }
    }
}

4.3 长时间运行的任务

/**
 * viewModelScope中的长时间任务
 */
class LongRunningTaskExample : ViewModel() {

    private val _progress = MutableStateFlow(0)
    val progress: StateFlow<Int> = _progress.asStateFlow()

    // 下载任务
    fun downloadFile(url: String) {
        viewModelScope.launch {
            try {
                downloadWithProgress(url) { progress ->
                    _progress.value = progress
                }
            } catch (e: CancellationException) {
                println("Download cancelled")
                throw e
            } catch (e: Exception) {
                println("Download failed: ${e.message}")
            }
        }
    }

    private suspend fun downloadWithProgress(
        url: String,
        onProgress: (Int) -> Unit
    ) {
        repeat(100) { i ->
            if (!isActive) return

            delay(100)
            onProgress(i + 1)
        }
    }

    // 数据同步任务
    private var syncJob: Job? = null

    fun startSync() {
        syncJob = viewModelScope.launch {
            while (isActive) {
                try {
                    syncData()
                    delay(300_000) // 5分钟
                } catch (e: Exception) {
                    println("Sync failed: ${e.message}")
                    delay(60_000) // 失败后1分钟重试
                }
            }
        }
    }

    fun stopSync() {
        syncJob?.cancel()
        syncJob = null
    }

    private suspend fun syncData() {}
}

4.4 与Repository协作

/**
 * ViewModel + Repository模式
 */
class ViewModelRepositoryExample {

    // Repository
    class UserRepository @Inject constructor(
        private val api: ApiService,
        private val database: UserDatabase
    ) {
        // Repository中的suspend函数
        suspend fun getUser(userId: String): User {
            return withContext(Dispatchers.IO) {
                try {
                    val user = api.getUser(userId)
                    database.userDao().insert(user)
                    user
                } catch (e: IOException) {
                    database.userDao().getUser(userId)
                        ?: throw e
                }
            }
        }

        // Repository中的Flow
        fun observeUser(userId: String): Flow<User> {
            return database.userDao()
                .observeUser(userId)
                .flowOn(Dispatchers.IO)
        }
    }

    // ViewModel
    class UserViewModel @Inject constructor(
        private val repository: UserRepository,
        private val savedStateHandle: SavedStateHandle
    ) : ViewModel() {

        private val userId: String
            get() = savedStateHandle.get<String>("user_id") ?: ""

        private val _user = MutableStateFlow<User?>(null)
        val user: StateFlow<User?> = _user.asStateFlow()

        init {
            loadUser()
            observeUser()
        }

        // 一次性加载
        private fun loadUser() {
            viewModelScope.launch {
                try {
                    val user = repository.getUser(userId)
                    _user.value = user
                } catch (e: Exception) {
                    Timber.e(e, "Failed to load user")
                }
            }
        }

        // 持续观察
        private fun observeUser() {
            viewModelScope.launch {
                repository.observeUser(userId)
                    .catch { e ->
                        Timber.e(e, "Failed to observe user")
                    }
                    .collect { user ->
                        _user.value = user
                    }
            }
        }

        // 更新用户
        fun updateUser(name: String) {
            viewModelScope.launch {
                try {
                    val updatedUser = user.value?.copy(name = name)
                        ?: return@launch

                    repository.updateUser(updatedUser)
                } catch (e: Exception) {
                    Timber.e(e, "Failed to update user")
                }
            }
        }
    }
}

data class User(val id: String, val name: String)

interface ApiService {
    suspend fun getUser(userId: String): User
}

interface UserDatabase {
    fun userDao(): UserDao
}

interface UserDao {
    suspend fun insert(user: User)
    suspend fun getUser(userId: String): User?
    fun observeUser(userId: String): Flow<User>
}

interface UserRepository {
    suspend fun updateUser(user: User)
}

5. 自定义作用域

5.1 创建自定义作用域

/**
 * 自定义协程作用域
 */
class CustomScopeExample {

    // 方式1: 实现CoroutineScope接口
    class MyComponent : CoroutineScope {
        private val job = SupervisorJob()
        override val coroutineContext: CoroutineContext
            get() = Dispatchers.Main + job

        fun doWork() {
            launch {
                processData()
            }
        }

        fun cleanup() {
            job.cancel()
        }

        private suspend fun processData() {
            delay(1000)
        }
    }

    // 方式2: 使用委托
    class AnotherComponent {
        private val scope = CoroutineScope(
            SupervisorJob() + Dispatchers.Main
        )

        fun doWork() {
            scope.launch {
                processData()
            }
        }

        fun cleanup() {
            scope.cancel()
        }

        private suspend fun processData() {
            delay(1000)
        }
    }

    // 方式3: MainScope
    class SimpleComponent {
        private val scope = MainScope()

        fun doWork() {
            scope.launch {
                processData()
            }
        }

        fun cleanup() {
            scope.cancel()
        }

        private suspend fun processData() {
            delay(1000)
        }
    }
}

5.2 配置自定义作用域

/**
 * 自定义作用域的配置
 */
class ScopeConfiguration {

    // 基础配置
    class BasicScope : CoroutineScope {
        override val coroutineContext = Job() + Dispatchers.Main
    }

    // 使用SupervisorJob
    class SupervisorScope : CoroutineScope {
        override val coroutineContext = SupervisorJob() + Dispatchers.Main
        // 子协程异常不会影响其他子协程
    }

    // 添加异常处理
    class ExceptionHandlingScope : CoroutineScope {
        private val exceptionHandler = CoroutineExceptionHandler { _, exception ->
            Timber.e(exception, "Coroutine failed")
        }

        override val coroutineContext =
            SupervisorJob() +
                    Dispatchers.Main +
                    exceptionHandler +
                    CoroutineName("MyScope")
    }

    // 自定义调度器
    class CustomDispatcherScope : CoroutineScope {
        private val customDispatcher = Executors.newFixedThreadPool(4)
            .asCoroutineDispatcher()

        override val coroutineContext =
            SupervisorJob() + customDispatcher

        fun cleanup() {
            coroutineContext.cancel()
            customDispatcher.close()
        }
    }

    // 限制并发数
    class LimitedScope : CoroutineScope {
        override val coroutineContext =
            SupervisorJob() +
                    Dispatchers.IO.limitedParallelism(2)
        // 最多2个任务同时运行
    }
}

5.3 作用域的生命周期管理

/**
 * 自定义作用域的生命周期管理
 */
class ScopeLifecycleManagement {

    // Repository作用域
    @Singleton
    class DataRepository @Inject constructor(
        private val api: ApiService,
        private val database: AppDatabase
    ) : CoroutineScope {

        private val job = SupervisorJob()
        override val coroutineContext = job + Dispatchers.IO

        // 预加载数据
        init {
            launch {
                preloadData()
            }
        }

        // 后台同步
        private var syncJob: Job? = null

        fun startBackgroundSync() {
            syncJob = launch {
                while (isActive) {
                    try {
                        syncData()
                        delay(300_000)
                    } catch (e: Exception) {
                        Timber.e(e, "Sync failed")
                        delay(60_000)
                    }
                }
            }
        }

        fun stopBackgroundSync() {
            syncJob?.cancel()
        }

        // 清理
        fun cleanup() {
            stopBackgroundSync()
            job.cancel()
        }

        private suspend fun preloadData() {}
        private suspend fun syncData() {}
    }

    // Service作用域
    class MyService : Service(), CoroutineScope {

        private val job = SupervisorJob()
        override val coroutineContext = job + Dispatchers.Main

        override fun onCreate() {
            super.onCreate()

            launch {
                doWork()
            }
        }

        override fun onDestroy() {
            job.cancel()
            super.onDestroy()
        }

        private suspend fun doWork() {}

        override fun onBind(intent: Intent?): IBinder? = null
    }

    // Application作用域
    class MyApplication : Application(), CoroutineScope {

        private val job = SupervisorJob()
        override val coroutineContext = job + Dispatchers.Main

        override fun onCreate() {
            super.onCreate()

            launch {
                initializeApp()
            }
        }

        override fun onTerminate() {
            job.cancel()
            super.onTerminate()
        }

        private suspend fun initializeApp() {}
    }
}

6. 生命周期管理

6.1 作用域取消

/**
 * 协程作用域的取消
 */
class ScopeCancellation {

    // 手动取消
    fun manualCancellation() {
        val scope = CoroutineScope(Job())

        scope.launch {
            try {
                repeat(100) {
                    delay(100)
                    println("Working $it")
                }
            } catch (e: CancellationException) {
                println("Cancelled")
            }
        }

        Thread.sleep(550)
        scope.cancel() // 取消作用域
    }

    // 取消并等待
    suspend fun cancelAndJoin() {
        val scope = CoroutineScope(Job())

        val job = scope.launch {
            try {
                delay(Long.MAX_VALUE)
            } finally {
                withContext(NonCancellable) {
                    println("Cleanup")
                    delay(1000)
                    println("Cleanup done")
                }
            }
        }

        delay(500)
        job.cancelAndJoin() // 取消并等待清理完成
        println("Job cancelled and joined")
    }

    // 检查取消状态
    fun checkCancellation() {
        val scope = CoroutineScope(Job())

        scope.launch {
            while (isActive) {
                // 定期检查是否被取消
                doWorkItem()
            }
            println("Coroutine finished")
        }
    }

    private fun doWorkItem() {}
}

6.2 作用域清理

/**
 * 协程作用域的资源清理
 */
class ScopeCleanup {

    class ResourceManager : CoroutineScope {
        private val job = SupervisorJob()
        override val coroutineContext = job + Dispatchers.IO

        private val resources = mutableListOf<Resource>()

        fun acquireResource(): Resource {
            val resource = Resource()
            resources.add(resource)

            launch {
                try {
                    resource.use()
                } finally {
                    // 清理资源
                    withContext(NonCancellable) {
                        resource.cleanup()
                        resources.remove(resource)
                    }
                }
            }

            return resource
        }

        fun cleanup() {
            // 取消所有协程
            job.cancel()

            // 清理所有资源
            resources.forEach { it.cleanup() }
            resources.clear()
        }

        class Resource {
            suspend fun use() {
                delay(Long.MAX_VALUE)
            }

            fun cleanup() {
                println("Resource cleaned up")
            }
        }
    }

    // 嵌套作用域清理
    suspend fun nestedCleanup() = coroutineScope {
        val resource1 = acquireResource()
        try {
            coroutineScope {
                val resource2 = acquireResource()
                try {
                    useResources(resource1, resource2)
                } finally {
                    resource2.cleanup()
                }
            }
        } finally {
            resource1.cleanup()
        }
    }

    private fun acquireResource(): Resource = Resource()
    private suspend fun useResources(r1: Resource, r2: Resource) {}

    class Resource {
        fun cleanup() {}
    }
}

6.3 作用域超时

/**
 * 协程作用域的超时控制
 */
class ScopeTimeout {

    // withTimeout: 超时抛异常
    suspend fun strictTimeout() {
        try {
            withTimeout(1000) {
                repeat(100) {
                    delay(100)
                    println("Working $it")
                }
            }
        } catch (e: TimeoutCancellationException) {
            println("Timeout!")
        }
    }

    // withTimeoutOrNull: 超时返回null
    suspend fun softTimeout() {
        val result = withTimeoutOrNull(1000) {
            delay(2000)
            "Result"
        }

        if (result == null) {
            println("Timeout!")
        } else {
            println("Got: $result")
        }
    }

    // 自定义超时处理
    suspend fun customTimeout() {
        val scope = CoroutineScope(Job())

        val job = scope.launch {
            try {
                processLongTask()
            } catch (e: CancellationException) {
                println("Task cancelled due to timeout")
            }
        }

        // 10秒后超时
        launch {
            delay(10_000)
            if (job.isActive) {
                job.cancel()
            }
        }

        job.join()
    }

    private suspend fun processLongTask() {
        delay(Long.MAX_VALUE)
    }
}

7. 作用域传播

7.1 父子作用域关系

/**
 * 作用域的父子关系
 */
class ScopePropagation {

    // 父作用域等待子作用域
    suspend fun parentWaitsChildren() = coroutineScope {
        launch {
            delay(1000)
            println("Child 1 done")
        }

        launch {
            delay(2000)
            println("Child 2 done")
        }

        println("Parent waiting...")
        // coroutineScope会等待所有子协程完成
    }

    // 父作用域取消传播到子作用域
    suspend fun parentCancelsChildren() {
        val parentScope = CoroutineScope(Job())

        parentScope.launch {
            launch {
                try {
                    delay(Long.MAX_VALUE)
                } catch (e: CancellationException) {
                    println("Child 1 cancelled")
                }
            }

            launch {
                try {
                    delay(Long.MAX_VALUE)
                } catch (e: CancellationException) {
                    println("Child 2 cancelled")
                }
            }

            delay(1000)
        }

        delay(500)
        parentScope.cancel()
        println("Parent cancelled, all children cancelled")
    }

    // 子作用域异常传播到父作用域
    suspend fun childExceptionPropagatesToParent() {
        try {
            coroutineScope {
                launch {
                    delay(500)
                    throw RuntimeException("Child failed")
                }

                launch {
                    delay(1000)
                    println("Won't execute")
                }
            }
        } catch (e: Exception) {
            println("Caught: ${e.message}")
        }
    }
}

7.2 supervisorScope隔离

/**
 * supervisorScope: 子协程失败不影响其他子协程
 */
class SupervisorScopeExample {

    // 独立失败
    suspend fun independentFailures() = supervisorScope {
        val job1 = launch {
            try {
                delay(500)
                throw RuntimeException("Job 1 failed")
            } catch (e: Exception) {
                println("Job 1 error: ${e.message}")
            }
        }

        val job2 = launch {
            delay(1000)
            println("Job 2 completed")
        }

        val job3 = launch {
            delay(1500)
            println("Job 3 completed")
        }

        // job1失败不会取消job2和job3
    }

    // 多个独立任务
    suspend fun multipleIndependentTasks() = supervisorScope {
        val tasks = listOf("Task1", "Task2", "Task3", "Task4", "Task5")

        tasks.forEach { task ->
            launch {
                try {
                    processTask(task)
                } catch (e: Exception) {
                    println("$task failed: ${e.message}")
                }
            }
        }
    }

    private suspend fun processTask(task: String) {
        delay(1000)
        if (task == "Task2") {
            throw RuntimeException("Failed")
        }
        println("$task completed")
    }

    // SupervisorJob
    class WorkerManager {
        private val scope = CoroutineScope(
            SupervisorJob() + Dispatchers.Default
        )

        fun startWorkers(count: Int) {
            repeat(count) { workerId ->
                scope.launch {
                    try {
                        workerTask(workerId)
                    } catch (e: Exception) {
                        println("Worker $workerId failed: ${e.message}")
                    }
                }
            }
        }

        private suspend fun workerTask(workerId: Int) {
            while (isActive) {
                delay(1000)
                println("Worker $workerId working")

                if (workerId == 2) {
                    throw RuntimeException("Worker 2 error")
                }
            }
        }

        fun shutdown() {
            scope.cancel()
        }
    }
}

8. deviceSecurity实战案例

8.1 案例1: 设备管理器生命周期

/**
 * 场景: deviceSecurity设备管理器
 *
 * 需求:
 * 1. 管理所有设备的协程
 * 2. 支持单个设备的独立管理
 * 3. 应用退出时清理所有资源
 */
@Singleton
class DeviceManager @Inject constructor(
    private val deviceRepository: DeviceRepository,
    private val connectionManager: ConnectionManager,
    @ApplicationContext private val context: Context
) : CoroutineScope {

    private val job = SupervisorJob()
    override val coroutineContext = job + Dispatchers.Main

    private val deviceScopes = mutableMapOf<String, Job>()

    init {
        // 启动设备发现
        launch {
            startDeviceDiscovery()
        }

        // 启动心跳检测
        launch {
            startHeartbeat()
        }
    }

    /**
     * 开始管理设备
     */
    fun manageDevice(deviceId: String) {
        // 如果已经在管理,先停止
        stopManagingDevice(deviceId)

        // 创建新的Job
        val deviceJob = launch {
            try {
                // 连接设备
                connectionManager.connect(deviceId)

                // 启动状态监控
                launch {
                    monitorDeviceStatus(deviceId)
                }

                // 启动数据同步
                launch {
                    syncDeviceData(deviceId)
                }

                // 启动事件监听
                launch {
                    listenDeviceEvents(deviceId)
                }

            } catch (e: CancellationException) {
                Timber.d("Device $deviceId management cancelled")
                throw e
            } catch (e: Exception) {
                Timber.e(e, "Failed to manage device $deviceId")
            } finally {
                withContext(NonCancellable) {
                    // 断开连接
                    connectionManager.disconnect(deviceId)
                    deviceScopes.remove(deviceId)
                }
            }
        }

        deviceScopes[deviceId] = deviceJob
    }

    /**
     * 停止管理设备
     */
    fun stopManagingDevice(deviceId: String) {
        deviceScopes[deviceId]?.cancel()
        deviceScopes.remove(deviceId)
    }

    /**
     * 设备发现
     */
    private suspend fun startDeviceDiscovery() {
        while (isActive) {
            try {
                val devices = deviceRepository.discoverDevices()
                devices.forEach { device ->
                    if (device.id !in deviceScopes) {
                        manageDevice(device.id)
                    }
                }
            } catch (e: Exception) {
                Timber.e(e, "Device discovery failed")
            }

            delay(30_000) // 30秒扫描一次
        }
    }

    /**
     * 心跳检测
     */
    private suspend fun startHeartbeat() {
        while (isActive) {
            try {
                deviceScopes.keys.forEach { deviceId ->
                    launch {
                        connectionManager.sendHeartbeat(deviceId)
                    }
                }
            } catch (e: Exception) {
                Timber.e(e, "Heartbeat failed")
            }

            delay(10_000) // 10秒发送一次心跳
        }
    }

    /**
     * 监控设备状态
     */
    private suspend fun monitorDeviceStatus(deviceId: String) {
        deviceRepository.observeDeviceStatus(deviceId)
            .catch { e ->
                Timber.e(e, "Failed to monitor device $deviceId")
            }
            .collect { status ->
                handleDeviceStatus(deviceId, status)
            }
    }

    /**
     * 同步设备数据
     */
    private suspend fun syncDeviceData(deviceId: String) {
        while (isActive) {
            try {
                val data = connectionManager.fetchDeviceData(deviceId)
                deviceRepository.saveDeviceData(deviceId, data)
            } catch (e: Exception) {
                Timber.e(e, "Failed to sync device $deviceId")
            }

            delay(60_000) // 1分钟同步一次
        }
    }

    /**
     * 监听设备事件
     */
    private suspend fun listenDeviceEvents(deviceId: String) {
        connectionManager.observeDeviceEvents(deviceId)
            .catch { e ->
                Timber.e(e, "Failed to listen events from device $deviceId")
            }
            .collect { event ->
                handleDeviceEvent(deviceId, event)
            }
    }

    /**
     * 处理设备状态
     */
    private suspend fun handleDeviceStatus(deviceId: String, status: DeviceStatus) {
        // 更新数据库
        deviceRepository.updateDeviceStatus(deviceId, status)

        // 检查异常状态
        if (status.isAbnormal) {
            // 发送通知
            sendNotification(deviceId, "设备异常")
        }
    }

    /**
     * 处理设备事件
     */
    private suspend fun handleDeviceEvent(deviceId: String, event: DeviceEvent) {
        when (event) {
            is DeviceEvent.MotionDetected -> {
                // 运动检测
                sendNotification(deviceId, "检测到移动")
            }
            is DeviceEvent.BatteryLow -> {
                // 电量低
                sendNotification(deviceId, "电量低")
            }
            is DeviceEvent.ConnectionLost -> {
                // 连接丢失
                stopManagingDevice(deviceId)
            }
        }
    }

    /**
     * 发送通知
     */
    private fun sendNotification(deviceId: String, message: String) {
        // 发送系统通知
    }

    /**
     * 清理
     */
    fun cleanup() {
        // 停止所有设备管理
        deviceScopes.keys.toList().forEach { deviceId ->
            stopManagingDevice(deviceId)
        }

        // 取消所有协程
        job.cancel()
    }
}

interface ConnectionManager {
    suspend fun connect(deviceId: String)
    suspend fun disconnect(deviceId: String)
    suspend fun sendHeartbeat(deviceId: String)
    suspend fun fetchDeviceData(deviceId: String): DeviceData
    fun observeDeviceEvents(deviceId: String): Flow<DeviceEvent>
}

interface DeviceRepository {
    suspend fun discoverDevices(): List<Device>
    fun observeDeviceStatus(deviceId: String): Flow<DeviceStatus>
    suspend fun saveDeviceData(deviceId: String, data: DeviceData)
    suspend fun updateDeviceStatus(deviceId: String, status: DeviceStatus)
}

data class Device(val id: String, val name: String)
data class DeviceData(val timestamp: Long, val data: String)
data class DeviceStatus(val isOnline: Boolean, val battery: Int) {
    val isAbnormal: Boolean = battery < 20 || !isOnline
}

sealed class DeviceEvent {
    object MotionDetected : DeviceEvent()
    object BatteryLow : DeviceEvent()
    object ConnectionLost : DeviceEvent()
}

8.2 案例2: 视频下载管理器

/**
 * 场景: deviceSecurity视频下载管理器
 *
 * 需求:
 * 1. 支持多个视频同时下载
 * 2. 限制并发下载数量
 * 3. 支持暂停/恢复/取消
 */
@Singleton
class VideoDownloadManager @Inject constructor(
    private val videoRepository: VideoRepository,
    private val storageManager: StorageManager
) : CoroutineScope {

    private val job = SupervisorJob()
    // 限制最多3个同时下载
    private val limitedDispatcher = Dispatchers.IO.limitedParallelism(3)
    override val coroutineContext = job + limitedDispatcher

    private val downloadJobs = mutableMapOf<String, Job>()
    private val _downloads = MutableStateFlow<Map<String, DownloadState>>(emptyMap())
    val downloads: StateFlow<Map<String, DownloadState>> = _downloads.asStateFlow()

    /**
     * 开始下载
     */
    fun download(videoId: String, url: String) {
        // 如果已经在下载,忽略
        if (videoId in downloadJobs) {
            return
        }

        // 更新状态为下载中
        updateDownloadState(videoId, DownloadState.Downloading(0))

        // 启动下载协程
        val downloadJob = launch {
            try {
                downloadVideo(videoId, url)
                updateDownloadState(videoId, DownloadState.Completed)
            } catch (e: CancellationException) {
                updateDownloadState(videoId, DownloadState.Cancelled)
                throw e
            } catch (e: Exception) {
                updateDownloadState(videoId, DownloadState.Failed(e.message ?: "下载失败"))
            } finally {
                downloadJobs.remove(videoId)
            }
        }

        downloadJobs[videoId] = downloadJob
    }

    /**
     * 下载视频
     */
    private suspend fun downloadVideo(videoId: String, url: String) {
        // 检查存储空间
        if (!storageManager.hasEnoughSpace()) {
            throw IOException("存储空间不足")
        }

        // 创建临时文件
        val tempFile = storageManager.createTempFile(videoId)

        try {
            // 下载数据
            videoRepository.downloadVideo(url) { progress ->
                updateDownloadState(videoId, DownloadState.Downloading(progress))
            }.collect { chunk ->
                // 写入文件
                tempFile.appendBytes(chunk)
            }

            // 移动到最终位置
            val finalFile = storageManager.moveToFinalLocation(videoId, tempFile)

            // 保存到数据库
            videoRepository.saveVideoFile(videoId, finalFile.absolutePath)

        } catch (e: Exception) {
            // 删除临时文件
            tempFile.delete()
            throw e
        }
    }

    /**
     * 暂停下载
     */
    fun pause(videoId: String) {
        downloadJobs[videoId]?.cancel()
        downloadJobs.remove(videoId)
        updateDownloadState(videoId, DownloadState.Paused)
    }

    /**
     * 恢复下载
     */
    fun resume(videoId: String, url: String) {
        // 重新开始下载
        download(videoId, url)
    }

    /**
     * 取消下载
     */
    fun cancel(videoId: String) {
        downloadJobs[videoId]?.cancel()
        downloadJobs.remove(videoId)
        updateDownloadState(videoId, DownloadState.Cancelled)

        // 删除临时文件
        launch {
            storageManager.deleteTempFile(videoId)
        }
    }

    /**
     * 取消所有下载
     */
    fun cancelAll() {
        downloadJobs.keys.toList().forEach { videoId ->
            cancel(videoId)
        }
    }

    /**
     * 更新下载状态
     */
    private fun updateDownloadState(videoId: String, state: DownloadState) {
        _downloads.value = _downloads.value.toMutableMap().apply {
            put(videoId, state)
        }
    }

    /**
     * 清理
     */
    fun cleanup() {
        cancelAll()
        job.cancel()
    }
}

/**
 * 下载状态
 */
sealed class DownloadState {
    data class Downloading(val progress: Int) : DownloadState()
    object Paused : DownloadState()
    object Completed : DownloadState()
    object Cancelled : DownloadState()
    data class Failed(val message: String) : DownloadState()
}

interface VideoRepository {
    fun downloadVideo(url: String, onProgress: (Int) -> Unit): Flow<ByteArray>
    suspend fun saveVideoFile(videoId: String, filePath: String)
}

interface StorageManager {
    fun hasEnoughSpace(): Boolean
    fun createTempFile(videoId: String): File
    fun moveToFinalLocation(videoId: String, tempFile: File): File
    suspend fun deleteTempFile(videoId: String)
}

8.3 案例3: 实时事件流处理

/**
 * 场景: deviceSecurity实时事件流处理
 *
 * 需求:
 * 1. 处理多个设备的实时事件
 * 2. 根据Activity生命周期启停
 * 3. 事件优先级处理
 */
class EventStreamViewModel @Inject constructor(
    private val eventRepository: EventRepository,
    private val notificationManager: NotificationManager
) : ViewModel() {

    private val _events = MutableSharedFlow<DeviceEvent>(
        replay = 10,
        extraBufferCapacity = 100
    )
    val events: SharedFlow<DeviceEvent> = _events.asSharedFlow()

    private val _highPriorityEvents = MutableSharedFlow<DeviceEvent>()
    val highPriorityEvents: SharedFlow<DeviceEvent> = _highPriorityEvents.asSharedFlow()

    private var streamJob: Job? = null

    /**
     * 开始监听事件流
     */
    fun startListening(deviceIds: List<String>) {
        streamJob?.cancel()

        streamJob = viewModelScope.launch {
            supervisorScope {
                // 为每个设备创建独立的监听
                deviceIds.forEach { deviceId ->
                    launch {
                        listenDeviceEvents(deviceId)
                    }
                }

                // 处理高优先级事件
                launch {
                    processHighPriorityEvents()
                }
            }
        }
    }

    /**
     * 停止监听
     */
    fun stopListening() {
        streamJob?.cancel()
        streamJob = null
    }

    /**
     * 监听单个设备的事件
     */
    private suspend fun listenDeviceEvents(deviceId: String) {
        eventRepository.observeDeviceEvents(deviceId)
            .catch { e ->
                Timber.e(e, "Failed to listen events from device $deviceId")
                // 错误不会取消其他设备的监听
            }
            .collect { event ->
                // 发送到事件流
                _events.emit(event)

                // 高优先级事件单独处理
                if (event.isHighPriority) {
                    _highPriorityEvents.emit(event)
                }
            }
    }

    /**
     * 处理高优先级事件
     */
    private suspend fun processHighPriorityEvents() {
        _highPriorityEvents.collect { event ->
            when (event) {
                is DeviceEvent.MotionDetected -> {
                    // 立即发送通知
                    notificationManager.sendNotification(
                        title = "检测到移动",
                        message = "设备 ${event.deviceId} 检测到移动"
                    )

                    // 开始录制
                    eventRepository.startRecording(event.deviceId)
                }

                is DeviceEvent.BatteryLow -> {
                    // 发送电量低通知
                    notificationManager.sendNotification(
                        title = "电量低",
                        message = "设备 ${event.deviceId} 电量低于 ${event.battery}%"
                    )
                }

                is DeviceEvent.ConnectionLost -> {
                    // 发送连接丢失通知
                    notificationManager.sendNotification(
                        title = "连接丢失",
                        message = "设备 ${event.deviceId} 连接丢失"
                    )
                }
            }
        }
    }
}

/**
 * Activity中使用
 */
class EventStreamActivity : AppCompatActivity() {

    private val viewModel: EventStreamViewModel by viewModels()
    private lateinit var binding: ActivityEventStreamBinding
    private val adapter = EventAdapter()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityEventStreamBinding.inflate(layoutInflater)
        setContentView(binding.root)

        setupRecyclerView()
        observeEvents()
    }

    private fun setupRecyclerView() {
        binding.recyclerView.apply {
            layoutManager = LinearLayoutManager(this@EventStreamActivity)
            adapter = this@EventStreamActivity.adapter
        }
    }

    private fun observeEvents() {
        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                // STARTED时开始监听
                viewModel.startListening(getDeviceIds())

                // 收集事件
                launch {
                    viewModel.events.collect { event ->
                        adapter.addEvent(event)
                        binding.recyclerView.smoothScrollToPosition(0)
                    }
                }

                // 收集高优先级事件
                launch {
                    viewModel.highPriorityEvents.collect { event ->
                        showHighPriorityAlert(event)
                    }
                }
            }

            // STOPPED时停止监听
            viewModel.stopListening()
        }
    }

    private fun getDeviceIds(): List<String> {
        // 获取设备ID列表
        return listOf("device1", "device2", "device3")
    }

    private fun showHighPriorityAlert(event: DeviceEvent) {
        MaterialAlertDialogBuilder(this)
            .setTitle("紧急事件")
            .setMessage(event.toString())
            .setPositiveButton("确定", null)
            .show()
    }
}

interface EventRepository {
    fun observeDeviceEvents(deviceId: String): Flow<DeviceEvent>
    suspend fun startRecording(deviceId: String)
}

interface NotificationManager {
    fun sendNotification(title: String, message: String)
}

val DeviceEvent.isHighPriority: Boolean
    get() = this is DeviceEvent.MotionDetected || this is DeviceEvent.BatteryLow

val DeviceEvent.deviceId: String
    get() = when (this) {
        is DeviceEvent.MotionDetected -> "deviceId"
        is DeviceEvent.BatteryLow -> "deviceId"
        is DeviceEvent.ConnectionLost -> "deviceId"
    }

val DeviceEvent.BatteryLow.battery: Int
    get() = 10

class EventAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    private val events = mutableListOf<DeviceEvent>()

    fun addEvent(event: DeviceEvent) {
        events.add(0, event)
        notifyItemInserted(0)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        TODO()
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        TODO()
    }

    override fun getItemCount(): Int = events.size
}

9. 最佳实践

9.1 选择合适的作用域

/**
 * 最佳实践: 选择合适的协程作用域
 */
class ScopeSelection {

    // ✅ 推荐: Activity/Fragment使用lifecycleScope
    class MyActivity : AppCompatActivity() {
        fun loadData() {
            lifecycleScope.launch {
                // Activity销毁时自动取消
                val data = fetchData()
                updateUI(data)
            }
        }

        private suspend fun fetchData(): String = "Data"
        private fun updateUI(data: String) {}
    }

    // ✅ 推荐: ViewModel使用viewModelScope
    class MyViewModel : ViewModel() {
        fun loadData() {
            viewModelScope.launch {
                // ViewModel清除时自动取消
                // 配置改变时不会取消
                processData()
            }
        }

        private suspend fun processData() {}
    }

    // ✅ 推荐: Repository使用自定义作用域
    @Singleton
    class MyRepository : CoroutineScope {
        private val job = SupervisorJob()
        override val coroutineContext = job + Dispatchers.IO

        fun cleanup() {
            job.cancel()
        }
    }

    // ❌ 不推荐: 使用GlobalScope
    class BadExample {
        fun doWork() {
            GlobalScope.launch {
                // 无法控制生命周期
            }
        }
    }
}

9.2 正确使用repeatOnLifecycle

/**
 * 最佳实践: 正确使用repeatOnLifecycle
 */
class RepeatOnLifecycleBestPractice : AppCompatActivity() {

    private val viewModel: MyViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // ✅ 推荐: 使用repeatOnLifecycle收集Flow
        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                viewModel.uiState.collect { state ->
                    updateUI(state)
                }
            }
        }

        // ✅ 推荐: 收集多个Flow
        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                launch {
                    viewModel.uiState.collect { updateUI(it) }
                }
                launch {
                    viewModel.events.collect { handleEvent(it) }
                }
            }
        }

        // ❌ 不推荐: 直接在lifecycleScope中收集
        // 问题: Activity在后台时仍然收集
        lifecycleScope.launch {
            viewModel.uiState.collect { state ->
                updateUI(state)
            }
        }
    }

    private fun updateUI(state: UiState) {}
    private fun handleEvent(event: Event) {}
}

9.3 正确管理作用域生命周期

/**
 * 最佳实践: 正确管理作用域生命周期
 */
class ScopeLifecycleManagement {

    // ✅ 推荐: Service中管理作用域
    class MyService : Service(), CoroutineScope {
        private val job = SupervisorJob()
        override val coroutineContext = job + Dispatchers.Main

        override fun onCreate() {
            super.onCreate()
            launch {
                doWork()
            }
        }

        override fun onDestroy() {
            job.cancel() // 取消所有协程
            super.onDestroy()
        }

        private suspend fun doWork() {}

        override fun onBind(intent: Intent?): IBinder? = null
    }

    // ✅ 推荐: 自定义组件管理作用域
    class MyComponent : CoroutineScope {
        private val job = SupervisorJob()
        override val coroutineContext = job + Dispatchers.Main

        fun start() {
            launch {
                doWork()
            }
        }

        fun stop() {
            job.cancel()
        }

        private suspend fun doWork() {}
    }

    // ❌ 不推荐: 忘记清理作用域
    class BadComponent {
        private val scope = CoroutineScope(Job())

        fun start() {
            scope.launch {
                // 永远不会被取消
                delay(Long.MAX_VALUE)
            }
        }

        // 缺少cleanup方法
    }
}

10. 常见问题FAQ

Q1: GlobalScope和自定义作用域有什么区别?

A:

  • GlobalScope: 全局作用域,生命周期是整个应用,无法控制
  • 自定义作用域: 可以控制生命周期,可以手动取消
// GlobalScope - 无法控制
GlobalScope.launch {
    // 一直运行直到应用关闭
}

// 自定义作用域 - 可以控制
val scope = CoroutineScope(Job())
scope.launch {
    // 工作
}
scope.cancel() // 可以取消

Q2: lifecycleScope和viewModelScope的区别?

A:

  • lifecycleScope: 绑定到Activity/Fragment生命周期,配置改变时会取消
  • viewModelScope: 绑定到ViewModel生命周期,配置改变时不会取消
// lifecycleScope - 配置改变时取消
class MyActivity : AppCompatActivity() {
    fun loadData() {
        lifecycleScope.launch {
            // 旋转屏幕时会取消
        }
    }
}

// viewModelScope - 配置改变时不取消
class MyViewModel : ViewModel() {
    fun loadData() {
        viewModelScope.launch {
            // 旋转屏幕时不会取消
        }
    }
}

Q3: repeatOnLifecycle有什么用?

A: 在指定生命周期状态重复执行,主要用于收集Flow

lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        // STARTED状态时执行
        // STOPPED状态时取消
        // 再次STARTED时重新执行
        viewModel.data.collect { data ->
            updateUI(data)
        }
    }
}

Q4: SupervisorJob和普通Job的区别?

A:

  • 普通Job: 子协程失败会取消所有兄弟协程
  • SupervisorJob: 子协程失败不影响其他子协程
// 普通Job
coroutineScope {
    launch { throw Exception() } // 失败
    launch { println("Won't execute") } // 被取消
}

// SupervisorJob
supervisorScope {
    launch { throw Exception() } // 失败
    launch { println("Will execute") } // 继续执行
}

Q5: 如何在Fragment中正确使用作用域?

A: 使用viewLifecycleOwner.lifecycleScope

class MyFragment : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        // ✅ 正确
        viewLifecycleOwner.lifecycleScope.launch {
            // View销毁时取消
        }

        // ❌ 错误
        lifecycleScope.launch {
            // Fragment detach时不会取消
        }
    }
}

Q6: 作用域取消后还能再次使用吗?

A: 不能,作用域取消后无法再次使用,需要创建新的作用域

val scope = CoroutineScope(Job())
scope.cancel()

scope.launch {
    // 不会执行!
}

// 需要创建新的作用域
val newScope = CoroutineScope(Job())
newScope.launch {
    // 可以执行
}

Q7: 如何等待作用域中所有协程完成?

A: 使用coroutineScope或保存Job并join

// 方式1: coroutineScope
suspend fun waitAll() = coroutineScope {
    launch { task1() }
    launch { task2() }
    // 自动等待所有协程完成
}

// 方式2: join
fun waitAll2() {
    val scope = CoroutineScope(Job())
    val job1 = scope.launch { task1() }
    val job2 = scope.launch { task2() }

    runBlocking {
        job1.join()
        job2.join()
    }
}

Q8: 如何在作用域中处理异常?

A: 使用CoroutineExceptionHandler或try-catch

// 方式1: ExceptionHandler
val handler = CoroutineExceptionHandler { _, e ->
    println("Caught: $e")
}
val scope = CoroutineScope(SupervisorJob() + handler)

// 方式2: try-catch
scope.launch {
    try {
        doWork()
    } catch (e: Exception) {
        println("Caught: $e")
    }
}

Q9: 什么时候使用supervisorScope?

A: 当子任务相互独立,一个失败不应影响其他时

supervisorScope {
    // 并发下载多个文件
    files.forEach { file ->
        launch {
            try {
                downloadFile(file)
            } catch (e: Exception) {
                println("$file failed")
            }
        }
    }
    // 一个文件下载失败不影响其他文件
}

Q10: 如何调试作用域问题?

A:

  1. 启用协程调试: -Dkotlinx.coroutines.debug
  2. 使用CoroutineName
  3. 检查作用域生命周期
  4. 使用Timber记录日志
val scope = CoroutineScope(
    Job() +
            Dispatchers.Main +
            CoroutineName("MyScope")
)

scope.launch {
    Timber.d("Running in ${coroutineContext[CoroutineName]}")
}

总结

本文全面介绍了协程作用域与生命周期管理:

核心概念

  1. 作用域类型: GlobalScope, lifecycleScope, viewModelScope, 自定义作用域
  2. 生命周期: 创建、运行、取消、清理
  3. 作用域传播: 父子关系、取消传播、异常传播
  4. supervisorScope: 隔离子协程失败

关键要点

  • 避免使用GlobalScope,使用生命周期感知的作用域
  • Activity/Fragment使用lifecycleScope
  • ViewModel使用viewModelScope
  • 自定义组件创建自己的作用域
  • 使用repeatOnLifecycle收集Flow
  • 使用supervisorScope隔离独立任务
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐