【问题标题】:Is Coroutine job auto cancelled upon exiting Activity?退出活动时协程作业是否自动取消?
【发布时间】:2021-02-13 09:18:39
【问题描述】:

我有以下加载缓慢图像的代码

class MainActivity : AppCompatActivity() {
    private lateinit var job: Job

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val imageLoader = ImageLoader.Builder(this)
            .componentRegistry { add(SvgDecoder(this@MainActivity)) }
            .build()

        job = MainScope().launch {
            try {
                val request = ImageRequest.Builder(this@MainActivity)
                    .data("https://restcountries.eu/data/afg.svg")
                    .build()
                val drawable = imageLoader.execute(request).drawable
                Log.d("TrackLog", "Loaded")
                findViewById<ImageView>(R.id.my_view).setImageDrawable(drawable)
            } catch (e: CancellationException) {
                Log.d("TrackLog", "Cancelled job")
            }
        }
    }

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

如果我在图像加载完成之前退出活动,我认为我应该手动执行job.cancel() 以取消协程。

但是,即使我注释掉了 job.cancel(),当我退出 MainActivity 时,作业仍然会被取消。

当我使用 GlobalScope 甚至使用全局变量范围和作业时也是如此。

val myScope = CoroutineScope(Dispatchers.IO)
private lateinit var job: Job

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val imageLoader = ImageLoader.Builder(this)
            .componentRegistry { add(SvgDecoder(this@MainActivity)) }
            .build()

        job = myScope.launch {
            try {
                val request = ImageRequest.Builder(this@MainActivity)
                    .data("https://restcountries.eu/data/afg.svg")
                    .build()
                val drawable = imageLoader.execute(request).drawable
                Log.d("TrackLog", "Loaded")
                findViewById<ImageView>(R.id.my_view).setImageDrawable(drawable)
            } catch (e: CancellationException) {
                Log.d("TrackLog", "Cancelled job")
            }
        }
    }

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

我很困惑,即使我不打电话给job.cancel(),当我们退出活动时,作业怎么会被取消。

【问题讨论】:

  • 是的,除非您以 launch(NonCancellable) {} 启动协程

标签: android kotlin coroutine


【解决方案1】:

显然,因为我的request 是由this@MainActivity 组成的

                val request = ImageRequest.Builder(this@MainActivity)
                    .data("https://restcountries.eu/data/afg.svg")
                    .build()

因此,在退出时,this@MainActivity 被杀死,因此 request 也被终止并可能被取消?

如果我们使用baseContext

                val request = ImageRequest.Builder(baseContext)
                    .data("https://restcountries.eu/data/afg.svg")
                    .build()

那么我们必须在onDestroy期间手动取消作业

因此使用lifecycleScope总是更安全

【讨论】:

    猜你喜欢
    • 2023-03-30
    • 2020-01-07
    • 1970-01-01
    • 1970-01-01
    • 2016-05-03
    • 1970-01-01
    • 1970-01-01
    • 2019-05-12
    • 2020-07-21
    相关资源
    最近更新 更多