2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ちょっと便利にするRx

Last updated at Posted at 2020-10-11

割とよく使う小技。

リジューム可能なsubcribe

一度、onErrorが呼ばれるとそのストリームに値を流せません。(すでにエラーが起きているよ。と値を流すと例外が飛んでくる)
イベントハンドラ的にobservableを使っていると、一度エラーが起きても復帰させて継続的にイベントを受けたいような時があると思います。
エラー → dispose → 再度subscribeなんていちいちやってられないので、そんな時は、一度 materialize すれば大丈夫です。

// T型を受けるコールバック関数
typealias OnNext<T> = (T) -> Unit
typealias OnError = (Throwable) -> Unit
typealias OnComplete = () -> Unit

@CheckReturnValue
fun <T> Observable<T>.resumeSubscribeBy(
    onError: OnError? = null,
    onComplete: OnComplete? = null,
    onNext: OnNext<T>? = null
): Disposable {
    return materialize()
        .subscribe {
            when {
                it.isOnError -> onError?.invoke(it.error!!)
                it.isOnNext -> {
                   // 例外時はonErrorに渡す
                    try {
                        onNext?.invoke(it.value!!)
                    } catch (e: Throwable) {
                        onError?.invoke(e)
                    }
                }
                it.isOnComplete -> onComplete?.invoke()
            }
        }
}

Notificationと合わせて使う

処理内容に応じて、通知を出し分けたい!
みたいなときありますよね。

拡張メソッドを利用して、以下な感じで。
notificationにしていますが、timberとかに変えてログを残すだけでもおすすめ。
特にスタックをログに残すようにすれば、どの処理かの特定がしやすくなります。

fun <T> Single<T>.withNotification(context: context, notificationBuilder: NotificationCompat.Builder, notificationContent: String): Single<T> {
// val stack = Throwable() // スタックトレース用

    return this.doOnSubscribe {
            notificationBuilder.setContentText("${notificationContent}の処理開始")

            val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.notify(notificationId, notificationBuilder.build())
        }
        .doOnError { err ->
            notificationBuilder.setContentText("${notificationContent}の処理中にエラーが発生しました")

            val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.notify(notificationId, notificationBuilder.build())
        }
        .doOnSuccess {
            notificationBuilder.setContentText("${notificationContent}のを実行しました")

            val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.notify(notificationId, notificationBuilder.build())
        }
}

リトライ

リトライ回数とリトライ間隔を調整したい!
みたな時はよくあるケースです。

flowable
    .take(10) // リトライ数
    .flatMapSingle { err ->
        // 間隔
        return@flatMapSingle Single.timer(1000, TimeUnit.MILLISECONDS)
    }

分岐

分岐して実行されるストリームを変える。みたいな時。flatMapを使いましょう!


val a = Random.nextInt(10)

Observable.just(a)
    .flatMap {
        if(it == 1) {
            return@flatMap Observable.just("a は 1です!!")
        }
        else {
            return@flatMap Observable.just("1じゃなかったーーー")
        }
    }
    .subscribe {
        Timber.d("結果:${it}")
    }

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?