ActivityとFragmentでGlobalScope
を使わないでコルーチンを利用する方法です。
GlobalScope
を何気なく使わないようにしましょう。
Do not use GlobalScope in local scope
At First. Look at follow code.
This example code is wrong coroutine usage.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)
GlobalScope.launch {
val data = withContext(Dispatchers.IO) {
loadData()
}
initUi(data)
}
}
...
}
This is a bad way.
But Why?
According to Officially GlobalScope explains at "GlobalScope - kotlinx-coroutines-core", GlobalScope's lifecycle scope is Process-Level. So, this loading data may keep running after Activity(also Fragment) Destroyed, and then happen unexpected behavior.
How to use Coroutines on Activity and Fragment without GlobalScope : Use LifecycleScope
Use androidx.lifecycle:lifecycle-runtime-ktx:2.2.0-alpha01
or higher.
So you can write like this example.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)
lifecycleScope.launch {
val data = withContext(Dispatchers.IO) {
loadData()
}
initUi(data)
}
}
...
}
In Fragment, use viewLifecycleOwner.
class MyFragment: Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewLifecycleOwner.lifecycleScope.launch {
val data = withContext(Dispatchers.IO) {
loadData()
}
initUi(data)
}
}
...
}
Because LifecycleScope
is lifecycle-aware, so if you want to use asynchronous tasks with only Activity and Fragment lifecycle scopes, it makes more sense to use LifecycleScope than GlobalScope.
See more: https://developer.android.com/topic/libraries/architecture/coroutines