首页 > 解决方案 > 退出活动时协程作业是否自动取消?

问题描述

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

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()
    }
}

我很困惑当我们退出 Activity 时,即使我没有调用,作业是如何被取消的job.cancel()

标签: androidkotlincoroutine

解决方案


显然,因为 myrequest是由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


推荐阅读