笔友城堡 - 可定义的个人主页

前言

继续记录Kotlin协程,上次封装了CoroutineScope ,现在就是如何控制退出呢,比如我启动一个任务后,我界面要消失了,因此任务也要取消。

简单记录于此,方便自己查阅。

流水文二,勿喷。

正文

接上文《Kotlin协程简单使用记录》中AppScope

object AppScope : CoroutineScope {
    override val coroutineContext =
        SupervisorJob() + Dispatchers.Default
}

⚠️ 注意:必须是 SupervisorJob(),否则一个任务 cancel,全部跟着死。

下面简单的展示如何取消任务。

var job = AppScope.launch {
    delay(1000)
    Log.d(TAG, "onResume 1 : delay 1000  " + Thread.currentThread().name)
}

job.cancel("MainActivity onResume")

统一管理job

方式 1

启动任务并持有

class UploadManager {
    // 保存单个任务
    private val uploadJob: Job? = null

    fun startUpload() {
        val job = AppScope.launch {
            //耗时操作
        }
        uploadJob = job
    }

    fun stopUpload() {
        uploadJob?.cancel("User cancel upload")
        uploadJob = null
    }
}
  1. 只取消上传任务

  2. 不影响 AppScope 其他任务

方式2

多个任务,通过Map管理

object TaskManager {
    private val tasks = ConcurrentHashMap<String, Job>()

    fun launchTask(
        name: String,
        block: suspend CoroutineScope.() -> Unit
    ): Job {
        val job = AppScope.launch(block = block)
        tasks[name] = job

        job.invokeOnCompletion {
            tasks.remove(name)
        }
        return job
    }

    fun cancelTask(name: String) {
        tasks[name]?.cancel("Task $name cancelled")
    }

    fun cancelAll() {
        tasks.values.forEach { it.cancel() }
        tasks.clear()
    }
}

使用

TaskManager.launchTask("sync") {
    while (true) {
        delay(2000)
        Log.d("Sync", "syncing...")
    }
}

// 取消指定任务
TaskManager.cancelTask("sync")

这是 SDK / 后台任务 / 长连接管理 的标准做法。

小结

  1. AppScope 本身不能也不应该“按任务取消

  2. 每个任务自己持有 Job,用 Job.cancel()

也就是取消任务似乎通过Job的!

AppScope的职责只有一个:App 进程活着,它就活着;App 死了,它全 cancel

参考文章

  1. AI

  2. Kotlin协程简单使用记录

相关文章

笔友城堡 - 可定义的个人主页

暂无评论

评论审核已启用。您的评论可能需要一段时间后才能被显示。

none
暂无评论...