[Android] Room +RxJava(Kotlin)でデータベースの変更通知を受け取る

はい。ほぼこの記事の使いまわしです!

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だとObservableFlowableの書き方が一緒になるね。

使ってみる

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]

まぁ、当たり前なのかもしれないけど、SingleMaybeonNext持ってないから、1度通知もらっちゃったら2度めの通知は来ない。

onNextを持っているObservableFlowableがDB更新の度に通知されてくれるって結果になった(当たり前)

タイトルとURLをコピーしました