#kotlin #kotlin-coroutines
#kotlin #kotlin-сопрограммы
Вопрос:
У меня есть приведенный ниже код, и я намеренно вызываю исключение, которое будет перехвачено errorHandler
private var coroutineScope: CoroutineScope? = null
private val mainThreadSurrogate = newSingleThreadContext("Test Main")
@Before
fun setUp() {
Dispatchers.setMain(mainThreadSurrogate)
}
@After
fun tearDown() {
// reset main dispatcher to the original Main dispatcher
Dispatchers.resetMain()
mainThreadSurrogate.close()
}
private val errorHandler = CoroutineExceptionHandler { context, error ->
println("Launch Exception ${Thread.currentThread()}")
coroutineScope?.launch(Dispatchers.Main) {
println("Launch Exception Result ${Thread.currentThread()}")
}
}
@Test
fun testData() {
runBlocking {
coroutineScope = MainScope()
coroutineScope?.launch(errorHandler) {
println("Launch Fetch Started ${Thread.currentThread()}")
throw IllegalStateException("error")
}?.join()
}
}
Это приведет к
Launch Fetch Started Thread[Test Main @coroutine#2,5,main]
Launch Exception Thread[Test Main @coroutine#2,5,main]
Launch Exception Result Thread[Test Main @coroutine#3,5,main]
Если я изменю coroutineScope = MainScope()
либо
coroutineScope = CoroutineScope(Dispatchers.Main)
coroutineScope = CoroutineScope(Dispatchers.IO)
coroutineScope?.launch(Dispatchers.Main) {...}
Не будет выполняться, т.Е. Launch Exception Result ...
Не будет распечатан.
Почему это так?
Ответ №1:
По-видимому, нам нужно создать область с использованием SupervisorJob()
, чтобы родительское задание не зависело от сбоя дочернего задания.
coroutineScope = CoroutineScope(SupervisorJob() Dispatchers.IO)
Обратите внимание на MainScope()
is CoroutineScope(SupervisorJob() Dispatchers.Main)
.
Как упоминалось в SupervisorJob
Сбой или отмена дочернего элемента не приводит к сбою задания супервизора и не влияет на другие его дочерние элементы, поэтому супервизор может реализовать пользовательскую политику для обработки сбоев своих дочерних элементов