1. Try to use GlobalScope
GlobalScope is the implementation class of Coroutinescope. The Launch and Async functions we have used before are the extensions of Coroutinescope.
GlobalScope does not bind any job object, which is used to build the top -level coroutine. The life cycle of these coroutines follows the Application.
Coroutines created in GlobalScope may cause application crash.
For example:
fun main() {
GlobalScope.launch {
throw RuntimeException("this is an exception")
"doSomething..."
}
Thread.sleep(5000)
}
Even in the main function, Try … Catch is trying to capture abnormalities, the following code is still thrown abnormal.
fun doSomething(): Deferred<String> = GlobalScope.async {
throw RuntimeException("this is an exception")
"doSomething..."
}
fun main() {
try {
GlobalScope.launch {
doSomething().await()
}
} catch (e:Exception) {
}
Thread.sleep(5000)
}
This is because the child Coroutine is created in the dosomething (), and the abnormality of the child Coroutine will cause the entire application to collapse.
Next, through a custom Coroutinescope, and its CoroutineContext is added to the Job object, the JOB object can directly manage the coroutine. But the child Coroutine may still throw an abnormality, causing the application to collapse.
val job: Job = Job()
val scope = CoroutineScope(Dispatchers.Default+job)
fun doSomething(): Deferred<String> = scope.async {
throw RuntimeException("this is an exception")
"doSomething..."
}
fun main() {
try {
scope.launch {
doSomething().await()
}
} catch (e:Exception) {
}
Thread.sleep(5000)
}
2. Supervisorjob, Coroutineexceptionhandler’s use
Coroutines created by GlobalScope have been introduced earlier that may lead to Crash.
For example:
text1.setOnClickListener {
GlobalScope.launch(UI) {
Toast.makeText(mContext,"cannot handle the exception", Toast.LENGTH_SHORT).show()
throw Exception("this is an exception")
}
}
If you can create a Coroutinescope, Coroutines created by the Coroutinescope can still be captured even if it is thrown abnormally, which will be ideal.
For example:
text2.setOnClickListener {
uiScope().launch {
Toast.makeText(mContext,"handle the exception", Toast.LENGTH_SHORT).show()
throw Exception("this is an exception")
}
}
If you can do some treatment for abnormalities, it will be better.
For example:
text3.setOnClickListener {
val errorHandle = object : CoroutineErrorListener {
override fun onError(throwable: Throwable) {
Log.e("errorHandle",throwable.localizedMessage)
}
}
uiScope(errorHandle).launch {
Toast.makeText(mContext,"handle the exception", Toast.LENGTH_SHORT).show()
throw Exception("this is an exception")
}
}
UISCOPE is a Coroutinescope created by calling SafecoroutinesCope.
The CoroutineContext of
SafeCoroutinescope uses Supervisorjob and CoroutineExceptionhandler.
SUPERVISORJOB’s sub -Job does not affect each other. The failure of a child Job will not affect the execution of other sub -JOB.
Coroutineexceptionhandler and use
Thread.uncaughtExceptionHandler
Very similar. Coroutineexceptionhandler is used to be universalcatch
code block is used to customize log records or abnormal processing in the corporation.
Let’s take a look at their packaging:
val UI: CoroutineDispatcher = Dispatchers.Main
fun uiScope(errorHandler: CoroutineErrorListener?=null) = SafeCoroutineScope(UI,errorHandler)
class SafeCoroutineScope(context: CoroutineContext, errorHandler: CoroutineErrorListener?=null) : CoroutineScope, Closeable {
override val coroutineContext: CoroutineContext = SupervisorJob() + context + UncaughtCoroutineExceptionHandler(errorHandler)
override fun close() {
coroutineContext.cancelChildren()
}
}
class UncaughtCoroutineExceptionHandler(val errorHandler: CoroutineErrorListener?=null) :
CoroutineExceptionHandler, AbstractCoroutineContextElement(CoroutineExceptionHandler.Key) {
override fun handleException(context: CoroutineContext, throwable: Throwable) {
throwable.printStackTrace()
errorHandler?.let {
it.onError(throwable)
}
}
}
So, when you click the Text2, Text3 button, you will not cause the App Crash.
When you click Text4, even if the Zi Coroutine throws an exception, it will not cause the app crash
text4.setOnClickListener {
uiScope().launch {
try {
uiScope().async {
throw RuntimeException("this is an exception")
"doSomething..."
}.await()
} catch (e: Exception) {
}
}
Toast.makeText(mContext,"handle the exception", Toast.LENGTH_SHORT).show()
}
3. Create AutoDISPOSESCOPE in View
Coroutines created in Android View needs to be bound to the life cycle of View.
The extended attribute of the View attributes defined below AutoDISPOSPOSCOPE, also uses SafeCoroutineScope.
// Create AutoDISPOSCOPE in Android View to support the main thread operation, abnormal processing, and job automatic Disposable in the life cycle of View
Val View.AutodisposeScope: Coroutinescope
get () {{
Return Safecoroutinescope
}
With AutodisposeScope, a Coroutinescope, you can use Coroutines with confidence in view.
text2.setOnClickListener {
text2.autoDisposeScope.launch {
doSomeWork()
}
}
4. Summary
Last year“AAC’s Lifecycle combined with Kotlin Coroutines for use”
In the article of, I have introduced the library I encapsulated: https://github.com/fengzhizi715/lifecycle-coroutines-Exquness, this article is an upgrade of the library, and it is also a summary of the experience of recent Kotlin Coroutines.
https://github.com/fengzhizi715/lifecycle-coroutines-Extense is not only a packaging for Lifecycle, but also a package used for Coroutines.
Follow[Java and Android Technology stack]
For more exciting content, pleaseFollow: