はい。ほぼこの記事の使いまわしです!
LiveDataで出来るんだからRxでも出来るでしょ!って感じでやってみたやつ。
Rxのことはあまりまだわかってないから検証も兼ねて!
RxでもLiveDataと同じような感じでできてお手軽だった!
ってことで実装。
実装
依存
// Room
def room_version = "2.2.2"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version"
implementation "androidx.room:room-rxjava2:$room_version"
// RX
implementation 'io.reactivex.rxjava2:rxjava:2.2.9'
implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
RoomでRx使うためのライブラリ(androidx.room:room-rxjava2)が用意されていた!
Daoクラス
// Dao
@Dao
interface RxEntityDao {
@Query("select * from RxEntity order by datetime desc")
fun getAllWithFlowable(): Flowable<List<RxEntity>>
@Query("select * from RxEntity order by datetime desc")
fun getAllWithObservable(): Observable<List<RxEntity>>
@Query("select * from RxEntity order by datetime desc")
fun getAllWithMaybe(): Maybe<List<RxEntity>>
@Query("select * from RxEntity order by datetime desc")
fun getAllWithSingle(): Single<List<RxEntity>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(rxEntity: RxEntity): Completable
@Query("delete from RxEntity")
fun deleteAll(): Completable
}
これもまた、戻り値をRxっぽいのにするだけ。
これでコードが自動生成されてくれる。お手軽!
今回は検証も兼ねて、いろいろな戻り値でメソッド作ってみた!
ViewModel
// Base
abstract class RxViewModel : ViewModel() {
protected val disposables = CompositeDisposable()
override fun onCleared() {
super.onCleared()
disposables.dispose()
}
}
disposeを自動でやってほしくて、とりあえずBase用意。
// ViewModel
class MainViewModel : RxViewModel() {
fun getRxDeEntity() {
Log.d("hoge", "getRxDeEntity")
// Flowable
App.db.rxEntityDao().getAllWithFlowable()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeBy(
onNext = {
Log.d("hoge", "Flowable onNext = ${it.map { it.hoge }}")
},
onComplete = {
Log.d("hoge", "Flowable onComplete")
},
onError = {
Log.d("hoge", "Flowable onError = ${it.message}")
}
).addTo(disposables)
// Observable
App.db.rxEntityDao().getAllWithObservable()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeBy(
onNext = {
Log.d("hoge", "Obserble onNext = ${it.map { it.hoge }}")
},
onComplete = {
Log.d("hoge", "Obserble onComplete")
},
onError = {
Log.d("hoge", "Obserble onError = ${it.message}")
}
).addTo(disposables)
// Maybe
App.db.rxEntityDao().getAllWithMaybe()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeBy(
onSuccess = {
Log.d("hoge", "Maybe onSuccess = ${it.map { it.hoge }}")
},
onComplete = {
Log.d("hoge", "Maybe onComplete")
},
onError = {
Log.d("hoge", "Maybe onError = ${it.message}")
}
).addTo(disposables)
// Single
App.db.rxEntityDao().getAllWithSingle()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeBy(
onSuccess = {
Log.d("hoge", "Single onSuccess = ${it.map { it.hoge }}")
},
onError = {
Log.d("hoge", "Single onError = ${it.message}")
}
).addTo(disposables)
}
fun rxDeInsert(rxEntity: RxEntity) {
Log.d("hoge", "rxDeInsert")
App.db.rxEntityDao().insert(rxEntity)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeBy(
onComplete = {
Log.d("hoge", "rxDeInsert onComplete")
},
onError = {
Log.d("hoge", "rxDeInsert onError")
}
).addTo(disposables)
}
}
各々のメソッドで取得する処理を書いてあるだけ。
これはログ出力してるだけだけど、LiveDataかなんかでView側にデータを通知してあげると良いと思う。
LiveDataで変更通知受け取るより、Rxで変更受け取ったほうがデータの加工はしやすいかな?って書いてて思った。
Rx難しいけど、、、。
RxKotlinだとObservableとFlowableの書き方が一緒になるね。
使ってみる
class MainFragment : Fragment() {
companion object {
fun newInstance() = MainFragment()
}
private lateinit var viewModel: MainViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return inflater.inflate(R.layout.main_fragment, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java).apply {
getRxDeEntity()
var count = 0
message.setOnClickListener {
count++
rxDeInsert(RxEntity("hoge$count"))
}
}
}
}
画面タップする度にDBにInsertする感じ。
ログ
// 初回起動
23:30:39.475 13567-13567/? D/hoge: getRxDeEntity
23:30:39.584 13567-13567/? D/hoge: Single onSuccess = []
23:30:39.584 13567-13567/? D/hoge: Maybe onSuccess = []
23:30:39.584 13567-13567/? D/hoge: Obserble onNext = []
23:30:39.584 13567-13567/? D/hoge: Flowable onNext = []
// Insert(FlowaleとObserbleだけ受信)
23:31:07.141 13567-13567/? D/hoge: rxDeInsert
23:31:07.149 13567-13567/? D/hoge: rxDeInsert onComplete
23:31:07.153 13567-13567/? D/hoge: Obserble onNext = [hoge1]
23:31:07.153 13567-13567/? D/hoge: Flowable onNext = [hoge1]
// 2回目の起動
23:31:25.987 14068-14068/? D/hoge: getRxDeEntity
23:31:26.055 14068-14068/? D/hoge: Flowable onNext = [hoge1]
23:31:26.055 14068-14068/? D/hoge: Obserble onNext = [hoge1]
23:31:26.055 14068-14068/? D/hoge: Maybe onSuccess = [hoge1]
23:31:26.056 14068-14068/? D/hoge: Single onSuccess = [hoge1]
まぁ、当たり前なのかもしれないけど、SingleとMaybeはonNext持ってないから、1度通知もらっちゃったら2度めの通知は来ない。
onNextを持っているObservableとFlowableがDB更新の度に通知されてくれるって結果になった(当たり前)