2017-12-12 39 views
1

코 루틴과 함께 예외 처리가 어떻게 작동하는지 매우 혼란 스럽습니다.코 틀린 코 루틴 스왈 로우 예외

동기 코드처럼 예외를 전달하는 일시 중단 기능 체인을 가질 수 있기를 바랬습니다. 따라서 Retrofit이 IOException을 던지면 발표자와 같이 사용자에게 오류를 표시하는 등의 일시 중지 기능 체인의 시작 부분에서 해당 예외를 처리 할 수 ​​있습니다.

코 루틴을 시험해보기 위해이 간단한 예제를 만들었지 만, throw Exception 코드를 호출하면 예외를 실행하지 못하고 코드를 호출해도 예외가 발생해도 응용 프로그램이 중단되지 않습니다.

package com.example.myapplication 

import android.os.Bundle 
import android.support.v7.app.AppCompatActivity 
import android.widget.Button 
import android.widget.TextView 
import kotlinx.coroutines.experimental.delay 
import kotlinx.coroutines.experimental.launch 

class MainActivity : AppCompatActivity() { 

    override fun onCreate(savedInstanceState: Bundle?) { 
     super.onCreate(savedInstanceState) 
     setContentView(R.layout.activity_main) 

     val text = findViewById<TextView>(R.id.thing_text) 
     val button = findViewById<Button>(R.id.thing_button) 

     var count = 0 

     button.setOnClickListener { 
      launch { 
       count++ 
//    throw Exception("Boom") 
       val string = delayedStringOfInt(count) 
       runOnUiThread { text.text = string } 
      } 
     } 
    } 

    suspend fun delayedStringOfInt(int: Int): String { 
     delay(1000) 
//  throw Exception("Boom") 
     return int.toString() 
    } 
} 

나는 asyncCoroutineExceptionHandler를 사용하여 시도했다.

답변

1

async을 사용하는 경우 결과는 어딘가에서 await이되므로 예외를 잃지 않습니다.

+0

나는 전에 await''와'async'을 시도했지만이 기능을 일시 중단하는 것은 단지 코 루틴에서 호출해야 기다리고 있습니다 '불평이나 또 다른 runBlocking'이 중단없이 작동'에 모든 포장, 그러나 function.'을 중지 비동기 코드 실행 'runBlocking'은 내부의 coroutines가 완성 될 때까지 블록하기를 기대하면서 혼란스러운 이름입니다. 내 경우에는 당신이 신속하게 버튼을 클릭하면 즉각적으로보다는 매초마다 숫자가 증가 할 것으로 예상됩니다. 나는 이것을 답으로 표시 할 것이지만 고정 된 코드를 다른 답에 넣을 것이다. – TTransmit

+0

더 자세히 살펴보면 runBlocking이 UI 스레드를 차단하고있는 것을 볼 수 있는데, 이는 내가 원하는 것이 아닙니다. 나는 콜백을 사용해보아야 할 것이다. – TTransmit

+0

kotlinx'Continuation'을 사용하면 지금까지 나에게 추한 콜백 지옥을 제공 할 수 있습니다. – TTransmit

0

다음은 Alexey Romanov의 대답을 기반으로 예외를 포착하는 코드입니다. 좀 더 많은 작업을 통해 출시와 함께 작업하게되었습니다. Log.d("thread", Thread.currentThread().name)을 추가하면 지연으로 인해 UI가 차단되지 않는다는 것을 알 수 있습니다.

class MainActivity : AppCompatActivity() { 

    override fun onCreate(savedInstanceState: Bundle?) { 
     super.onCreate(savedInstanceState) 
     setContentView(R.layout.activity_main) 

     val text = findViewById<TextView>(R.id.thing_text) 
     val button = findViewById<Button>(R.id.thing_button) 

     var count = 0 

     button.setOnClickListener { 
      launch { 
       val job = async { 
        count++ 

        val string = delayedStringOfInt(count) 
        updateTextView(text, string) 
       } 

       try { 
        job.await() 
       } catch (e: IOException) { 
        makeToastFromException(e) 
       } 
      } 
     } 
    } 

    fun makeToastFromException(e: Exception) { 
     runOnUiThread { 
      Toast.makeText([email protected], e.localizedMessage, Toast.LENGTH_SHORT).show() 
     } 
    } 

    fun updateTextView(text: TextView, string: String) { 
     runOnUiThread { text.text = string } 
    } 

    suspend fun delayedStringOfInt(int: Int): String { 
     delay(2000) 
     if (int % 4 == 0) throw IOException("Boom") 
     return int.toString() 
    } 
}