hayabusa PRAY

技術的で気になった事を書きます。Androidがメイン。

RxJavaを使ったエラーハンドリングをどうするか その1

前提

  • RxJavaでは例外が投げられた時、Observable#subscribeの引数onErrorにThrowableで渡って来る。

class ApiClient {
    fun fetchSomeData() : Single<SomeData> {
    // 取得処理
    }
}

利用側

apiClient.fetchSomeData()
     .subscribe ( {  data : SomeData -> /**  成功処理 */ }, { t: Throwable -> /** エラーハンドリング */ })

問題

  • どのようなエラーが返って来るかという情報がメソッド定義にない。
    • 実装を読まないとわからない ( = カプセル化されてない)
      • 大きめのコードの場合実装を追うのが大変

解決策

@OnError アノテーションを定義して、ハンドリングして欲しい例外はメソッド定義につける

/**
 * ハンドリングするべき例外をonErrorに流す場合、メソッドの返り値に付与する
 */
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.SOURCE)
@MustBeDocumented
annotation class OnError(vararg val klass: KClass<*>)

ハンドリングして欲しい例外の基準

ユーザーが回復可能かどうか。回復可能な場合、ハンドリングしてユーザーに回復方法を伝える価値がある。 以下の Recoverable Error の例が参考になった。

qiita.com

class ApiClient {
   @OnError(NetworkException::class, ApiException::class )
    fun fetchSomeData() : Single<SomeData> {
    // 取得処理
    }
}

利用側

apiClient.fetchSomeData()
     .subscribe ( {  data : SomeData -> /**  成功処理 */ }, { t: Throwable -> 
            when (t) {
                  is NetworkException -> toast("ネットワーク接続状態を確認してください。")
                  is ApiException -> toast("リクエストに失敗しました。時間を置いて再度お試しください。")
                  else ->  toast("失敗しました") //想定してない例外なのでとりあえずな文言を出して、裏でクラッシュレポーティングツールとかに伝えるのが良いんじゃないかと思う。
            }
})