Issue
What is the proper way to launch a coroutine from a click event that is defined in a fragment? From my understanding, GlobalScope.launch
is used if you want to launch a coroutine that is supposed to remain in memory for the entire lifecycle of the app. But since a fragment usually has a shorter lifecycle than the app, GlobalScope.launch
probably isn't the proper way. I assume that if I used GlobalScope.launch
, it might keep the fragment from being garbage collected?
I really only need to launch the coroutine from a click event handler, which means that there is no parent functions that I would be calling from.
Solution
You need a job
to handle the coroutine cancelation to prevent leaks:
//inside Fragment
val job = Job()
val uiScope = CoroutineScope(Dispatchers.Main + job)
//late in the button click
button.setOnClickListener{
uiScope.launch(Dispatchers.IO){
//asyncOperation
withContext(Dispatchers.Main){
//ui operation
}
}
}
//later in on destroy:
override fun onDestroy(){
job.cancel()
super.onDestroy()
}
You can also use LifecycleScope extension from Google:
class MyFragment: Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
lifecycleScope.launch {
val params = TextViewCompat.getTextMetricsParams(textView)
val precomputedText = withContext(Dispatchers.Default) {
PrecomputedTextCompat.create(longTextContent, params)
}
TextViewCompat.setPrecomputedText(textView, precomputedText)
}
}
}
Edit, in case you would re-fire another operation. Just use the same scope:
//let's assume you have a second button
button2.setOnClickListener{
uiScope.launch(Dispatchers.IO){
//perform second operation
}
}
Answered By - coroutineDispatcher
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.