DisposeとCancelの使い分けがいまいちわからない。
Flowableの処理を途中で停止する方法と、発生するイベントについて。基本的にはObsavableと同じなので、まずはこちらを参考にして欲しい。
Obsavableではsubscribeを実行したときに返値として得られるdisposableを利用してdispose()すればよかったが、FlowableではdoOnsubscribeで得られるsubscriptionのcancel()メソッドも利用できるのでややこしい。
挙動としてはdispose()するとcreate内に記述したsetCancellableのイベントと、doOnCancelのイベントの両方が実行されるが、cancel()ではsetCancellableのイベントしか発生しない。そしてその後にdispose()するとCancelイベントが発生する。
またdispose()するとisDisposedがtrueになるが、cancel()ではisDisposedはtrueにならない。なので、このcancel()はdispose扱いにならないので、cancel()してもdispose()することが必須になるようだ。
非同期処理はcancelでもdisposeでも停止する。
cancel()後にrequestすればバッファに残っているデータを引き出せるのかと思ったが、そのようなこともないので、処理を停止させる場合はdispose()しておけば間違いないようだ。
また、flowableもdisposeやcancelするとtry~catchがエラーをキャッチしてonErrorを実行してしまう。だが、flowableはdisposeされているので実行できずアプリが落ちるので、こちらもisDisposedやisCanceledを調べて実行されないようにしておく。
Flowableの処理を途中で停止する方法と、発生するイベントについて。基本的にはObsavableと同じなので、まずはこちらを参考にして欲しい。
Obsavableではsubscribeを実行したときに返値として得られるdisposableを利用してdispose()すればよかったが、FlowableではdoOnsubscribeで得られるsubscriptionのcancel()メソッドも利用できるのでややこしい。
挙動としてはdispose()するとcreate内に記述したsetCancellableのイベントと、doOnCancelのイベントの両方が実行されるが、cancel()ではsetCancellableのイベントしか発生しない。そしてその後にdispose()するとCancelイベントが発生する。
またdispose()するとisDisposedがtrueになるが、cancel()ではisDisposedはtrueにならない。なので、このcancel()はdispose扱いにならないので、cancel()してもdispose()することが必須になるようだ。
非同期処理はcancelでもdisposeでも停止する。
cancel()後にrequestすればバッファに残っているデータを引き出せるのかと思ったが、そのようなこともないので、処理を停止させる場合はdispose()しておけば間違いないようだ。
また、flowableもdisposeやcancelするとtry~catchがエラーをキャッチしてonErrorを実行してしまう。だが、flowableはdisposeされているので実行できずアプリが落ちるので、こちらもisDisposedやisCanceledを調べて実行されないようにしておく。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.v("null", Thread.currentThread().name)
var flowableDisposable: Disposable? = null
var subscription: Subscription? = null
var flowable = Flowable.create<String>({
Log.v("null", Thread.currentThread().name)
try {
//cancel()でもdispose()でもコールバックされる
it.setCancellable {
Log.v("null", "cancelable")
}
for (i: Int in 1..100) {
Thread.sleep(100)
Log.v("null", "store:" + i.toString())
it.onNext(i.toString())
}
it.onComplete()
} catch (e: Exception) {
//cancel()やdispose()時にcatchしてonErrorを実行してしまう
//このときdispose済みだとアプリが落ちるので回避する
if (flowableDisposable?.isDisposed == false && it.isCancelled == false) {
it.onError(Throwable("error"))
}
}
}, BackpressureStrategy.BUFFER)
.subscribeOn(Schedulers.computation())
.observeOn(Schedulers.computation())
.doOnSubscribe {
subscription = it
}
.doOnNext {
Log.v("null", it)
}
.doOnError {
Log.v("null", "error")
}
//dispose()の時にコールバックされるが、cancel()ではコールバックされない
.doOnCancel {
Log.v("null", "cancel")
}
//購読開始
button1.setOnClickListener {
flowableDisposable = flowable.subscribe({}, {}, {}, {})
}
//disposeする
button2.setOnClickListener {
flowableDisposable?.dispose()
}
//cancelする
button3.setOnClickListener {
subscription?.cancel()
}
}
}