简体   繁体   中英

Is Coroutine job auto cancelled upon exiting Activity?

I have the below code of a slow loading image

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

If I exit the activity before the image loaded completed, I thought I should manually perform job.cancel() to get the coroutine canceled.

However, even when I commented out the job.cancel() , the job still get canceled when I exit MainActivity .

This is also true when I use either GlobalScope or even use a global variable scope and job.

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

I'm puzzled how did the job get canceled when we exit the Activity even when I don't call job.cancel() .

Apparently, because my request is made of this@MainActivity

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

hence, when exiting, the this@MainActivity is killed, hence the request also got terminated and perhaps canceled?

If we use baseContext

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

then we have to manually cancel the job during onDestroy

Therefore it is always safer to use lifecycleScope

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM