RxJava2 & Room: Stop emitting events on delete - android

I have this database
interface UserDao {
#Insert(onConflict = REPLACE)
fun insert(user : User)
#Query("SELECT * FROM user")
fun get(): Flowable<List<User>>
#Query("DELETE FROM user")
fun deleteAll()
}
Everytime a record is inserted, get() will be triggered automatically, as expected.
override fun getUsers() : Flowable<User> {
return db.userDao().get()
}
How can I stop this from happening when deleteAll() is called?

You can use Single instead of Flowable. Secondly you can use a flag in your onNext() method of the subscriber. Turn the flag off after first run. Even if it gets triggered no changes will occur to your core code in onNext().

Related

DAO when to use suspend function android

I am following DAO tutorial on Android developers here:
https://developer.android.com/codelabs/android-room-with-a-view-kotlin#5
They say:
By default, all queries must be executed on a separate thread.
Room has Kotlin coroutines support. This allows your queries to be annotated with the suspend modifier and then called from a coroutine or from another suspension function.
Dao interface is as follows:
#Dao
interface WordDao {
#Query("SELECT * FROM word_table ORDER BY word ASC")
fun getAlphabetizedWords(): List<Word>
#Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(word: Word)
#Query("DELETE FROM word_table")
suspend fun deleteAll()
}
Why getAlphabetizedWords() is not defined as suspend function?
In coroutines, a flow is a type that can emit multiple values sequentially, as opposed to suspend functions that return only a single value. For example, you can use a flow to receive live updates from a database.
#Dao
interface WordDao {
// The flow always holds/caches latest version of data. Notifies its observers when the
// data has changed.
#Query("SELECT * FROM word_table ORDER BY word ASC")
fun getAlphabetizedWords(): Flow<List<Word>>
#Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(word: Word)
#Query("DELETE FROM word_table")
suspend fun deleteAll()
}
you can see source code in Github.

accessing kotlin Suspend function from Java code

I have Room database interface which is a Kotlin file and as I dont want the calls to run on mainthread I am using kotlin Suspend. how can I use suspend function from java
I have two method where I want to insert a User and another to retrieve the users
these are the errors I get in my java file
Code
Room Dao interface
UserDao
#Dao
interface UserDao {
fun getAllUsersAsync(): CompletableFuture<List<User>> =
GlobalScope.future { getAllUsers() }
#Query("SELECT * FROM user")
suspend fun getAllUsers(): List<User>
#Insert
suspend fun insertUser(user: User): Long
}
Java code
private Long addUser(com.i6systems.in2plane.AppDatabase.User user) {
return userDao.insertUser(user);
}
private List<com.i6systems.in2plane.AppDatabase.User> getUsers () {
return userDao.getAllUsersAsync();
}
your help is much appreciated
Thanks
R

Room #Transaction and Rx Completable

My dao looks like
#Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(group: Group): Completable
#Query("DELETE FROM groups")
fun deleteAllGroups()
I would like to refresh all rows like
#Transaction
fun refreshGroups(groups: List<Group>): Completable {
deleteAllGroups()
insertAll(groups)
}
However, I can't return Completable from Transaction.
I'm using Rx so I'm expecting some kind of Observable.

Obtain entity using coroutines api

What is the best way to use coroutines with LiveData for selecting some data from database using Room.
This is My Dao class with suspended selection
#Dao
interface UserDao {
#Query("SELECT * from user_table WHERE id =:id")
suspend fun getUser(id: Long): User
}
Inside of View Model class I load user with viewModelScope.
Does it correct way to obtain user entity ?
fun load(userId: Long, block: (User?) -> Unit) = viewModelScope.launch {
block(dao.getUser(userId))
}
According developer android mentioned
val user: LiveData<User> = liveData {
val data = database.loadUser() // loadUser is a suspend function.
emit(data)
}
This chunk of code does not work
Your Room must return LiveData.
Use instead:
#Dao
interface UserDao {
#Query("SELECT * from user_table WHERE id =:id")
fun getUser(id: Long): LiveData<User>
}

How return completable on room transaction Android

I need your help please.
I have dao interface that save some configurations:
#Dao interface ConfigDao {
#Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(config: Config)
#Update(onConflict = OnConflictStrategy.REPLACE)
fun update(config: Config)
#Query("select * from T_CONFIG where isSelected = :isSelected")
fun getConfig(isSelected: Boolean): Single<Config>
#Query("select * from t_config")
fun getConfigAll(): LiveData<MutableList<Config>>
#Query("update T_CONFIG set isSelected = :isSelected where idEnvironment = :id")
fun updateConfigById(id: String, isSelected: Boolean):Completable
#Transaction
fun updateConfigTransaction(configSelected: Config){
if (configSelected.idEnvironment == Environtment.Type.PRD.toString()){
updateConfigById(Environtment.Type.PRD.toString(), false)
updateConfigById(Environtment.Type.DEV.toString(), true)
}else{
updateConfigById(Environtment.Type.PRD.toString(), true)
updateConfigById(Environtment.Type.DEV.toString(), false)
}
}
}
I need to know when the transaction is complete with success or error.
I tried to implement Completable from io.reactivex but it's not possible.
Since Room 2.1.0
Additional Async Support: DAO methods annotated with #Insert, #Delete or #Update, along with #Query containing INSERT, DELETE or UPDATE statements, now support Rx return types Completable, Single, Maybe, and Guava's return type ListenableFuture, and they can also be suspend functions.
Source: https://developer.android.com/jetpack/androidx/releases/room#2.1.0
Older versions
Change the interface to an abstract class. You'll have to prefix all methods without implementation with abstract. Then:
abstract class ConfigDao(private val db: MyDatabase) {
private val scheduler = Schedulers.from(db.queryExecutor)
// Make sure the method is open so Room can generate the transaction handling code.
#Transaction
open fun updateConfigTransaction(configSelected: Config){
// ...
}
fun updateConfigTransactionAsync(configSelected: config): Completable {
return Completable
.fromAction { updateConfigTransaction(config) }
.subscribeOn(scheduler)
}
}
subscribeOn(db.queryExecutor) makes sure the query runs on the same thread as all other DAO methods returning RxJava types. Replace MyDatabase constructor parameter with whatever your database class is.

Categories

Resources