Drop delete trigger for Room database

2019-06-02 01:17发布

问题:

I am using room database to store comments and RxJava as a listener to do some stuff when the database is changed.

I want to not call the callback when delete is called on the table, only when insert is called.

What i found out so far is that Room library has triggers that are called on delete, insert and update of the table that in turn call RxJava's methods.

Is there any way to drop the delete trigger and get callbacks only for the insert and update methods?

Here is my CommentDAO:

@Query("SELECT * FROM comments" )
fun getAll(): Flowable<List<Comment>>

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(comment: Comment)

@Delete
fun delete(comment: Comment)

And my RxJava callback functions:

 /**
 * Inserts comment into comment database
 * 
 * @param object that's going to be inserted to the database
 */
fun saveComment(comment: Comment) {
    Observable.just(comment).subscribeOn(Schedulers.io()).map({ comment1 -> commentdb.commentDao().insert(comment1) }).subscribe()
}

/**
 * Removes comment from the database
 *
 * @param comment object that's going to be removed
 */

fun removeComment(comment: Comment){
    Observable.just(comment).subscribeOn(Schedulers.io()).map({ comment1 -> commentdb.commentDao().delete(comment1) }).subscribe()
}

fun createCommentObservable(uploader: CommentUploader) {
    commentdb.commentDao().getAll().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(
            {
                success -> uploader.queue(success)
            }
    )
}

回答1:

You can get a Flowable<List<Comment>> that only emits on insertions and not on deletions by filtering the original getAll() Flowable so that only those List<Comment> items are passed through that contain more Comments than the previous List<Comment>.

You can implement this filtering with the following transformations:

  1. Prepend the flowable with an empty list so that we have a baseline for insertions.
  2. Get RxJava window()s of size 2, so that we will be able to compare adjacent items.
  3. window() returns Flowable<Flowable<Comment>>. Convert it to Flowable<List<Comment>> with flatMap() and toList() on the inner Flowable.
  4. Filter those 2-element windows that represent an insertion (the size of the first element is less than the size of the second).
  5. Emit only the 2nd element of the filtered windows.

In Kotlin:

fun getAllAfterInsertions() {
    getAll()
            .startWith(emptyList<String>())                        // (1)
            .window(2, 1)                                          // (2)
            .flatMap({ w -> w.toList().toFlowable() })             // (3)
            .filter({ w -> w.size == 2 && w[0].size < w[1].size }) // (4)
            .map({ window -> window[1] })                          // (5)
}


回答2:

To delete without notification I simply replace

MyDao().delete()

with one executing a @Query

MyDao().deleteLast()

then thew Flowable doesn't emit a new event. The @Dao looks like this

@Dao
abstract class MyDao : BaseDao<Data> {

   @Query("DELETE FROM Data WHERE id = (select min(id) from Data)") // or something else
   abstract fun deleteLast()

   @Delete
   fun delete(data: Data)

}