How can I do a room transaction across 2 different DAOs usin rxjava?
I have this code that I would like to use with Rxjava but I need it to return some kind of observable
#Transaction
fun insertStoreWithPictures(store: Store, pictures: List<StorePicture>) {
insertStore(store)
insertPictures(pictures)
}
The store DAO
#Dao
abstract public class store {
#Insert
Single<Long> insert(store entity);
}
The storePicture DAO
#Dao
abstract public class storePicture {
#Insert
Completable insert(storePicture... entity);
}
I think you can use zip or combine operator of RxJava. It would create an observable from an iterators observable source.
Best example you can follow to achieve the same - https://blog.mindorks.com/understanding-rxjava-zip-operator-with-example
Related
I'm developing MVVM kotlin application with repository pattern
I have separated my model classes as below
classes represents the data coming from network
classes represents entities for the room database
classes that represents the domain
In my repository I want always to return the domain object not the network object or the entity object.
In my Dao I insert and retrieve entity object as below
#Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAsteroids(asteroid: List<AsteroidEntity>)
#Query("SELECT * FROM asteroid_tbl")
fun getAsteroidsFromDb () : LiveData<List<AsteroidEntity>>
And I have a function in the repository that returns the list of asteroids as Live data from room as below
override suspend fun getAsteroids(): LiveData<List<Asteroid>> {
return appLocalDb.asteroidDao.getAsteroidsFromDb()
}
But the issue is the dao returns a LiveData<List<AsteroidEntity>>
while the repository I want it to return the domain model as
LiveData<List<Asteroid>>
Any suggestion on how to solve this problem?
Use Transformations.map
override suspend fun getAsteroids(): LiveData<List<Asteroid>> {
return Transformations.map(appLocalDb.asteroidDao.getAsteroidsFromDb()) { it.map{ item -> Asteroid(item.name,....)} }
}
For Further Documentation checkout the docs
https://developer.android.com/reference/android/arch/lifecycle/Transformations
I'm posting my room query result using the below code
_data.postValue(databaseImpl.findRepoById(id).value)
But it seems the returned object is empty. I'm guessing we need to observe databaseImpl.findRepoById(id), not access it directly but since it's in a viewmodel I don't have a lifecycleOwner to assign to the room query livedata.
databaseImpl.observe(this, Observer { //!!this is modelview and not activity
_data.postValue()
})
What is the right way to use Room query and update a mediator live data?
You could try use coroutines to query your data so you can have something like this for your DAO:
#Query("SELECT * FROM users")
fun findRepoById(id): Flow<User>
In your DatabaseImpl class return have it as:
fun findRepoById(id): Flow<User> = userDao.findRepoById(id)
Then in your ViewModel you could do this:
viewModelScope.launch {
databaseImpl.findRepoById(id).map { _data.postValue(it) }
}
Have a look at this article Room and Coroutines by Florina Muntenescu
on how you could set up coroutines and use it with room.
I'm developing an android app with Kotlin.
I'm using RxJava and MVVM.
i tried this :
a link
Here is one of my method in DataSource interface
fun insertPhoneNumber(phoneNumber: PhoneNumber) : Long
fun insertAllPhoneNumber(phoneNumberList: List<PhoneNumber>): List<Long>
The question is, after building the basic classes and requirements.
The compiler issues an error as follows:
e: [kapt] An exception occurred: java.lang.IllegalArgumentException:
long cannot be converted to an Element
I want to return the corresponding ID when a record is stored in my table
If you're using RxJava your Dao interface should look like this...
#Dao
interface WhateverDao {
#Insert
fun insertPhoneNumber(phoneNumber: PhoneNumber) : Maybe<Long>
#Insert
fun insertAllPhoneNumber(vararg phoneNumberList: PhoneNumber): Maybe<List<Long>>
}
Changes are:
Mark the interface with #Dao
Mark insert methods with #Insert
Pass a vararg to the insert all method
Use RxJava classes on the return type to make use of the reactive-streams pattern
What i want to achieve is to wrap a specific type for room database query result
The same as we doing now with android.arch.persistence.room:rxjava2 library that helps to expose RxJava2 Types like Observables and Flowables in the result
example :
abstract Single<User> find(String id);
Is there any specific Adapter or a way that can help to acheive this wrapping ? or create and artifact same as android.arch.persistence.room:rxjava2
for Coroutines as an example
Add implementation "android.arch.persistence.room:rxjava2:1.1.0" to you build.gradle.
https://developer.android.com/training/data-storage/room/accessing-data#query-rxjava
#Dao
public interface MyDao {
#Query("SELECT * from user where id = :id LIMIT 1")
public Flowable<User> loadUserById(int id);
}
I have a situation which I haven't been able to solve via RxJava2 operators.
I have a list of "Matches" I retrieve from Room. Here is my Match POJO.
public class Match {
#PrimaryKey
private int id;
#Ignore
Team rivalTeam;
}
Here is my Dao for this table.
#Dao
public interface MatchDao {
#Query("select * from `match` where homeTeamId= :homeTeamId")
Single<List<Match>> getMatchesByTeamId(int homeTeamId);
}
My target is to create an observable which will pull out these matches and then merge it with an observable which would be returning the rivalTeam.
Here is my Team Dao
#Dao
public interface TeamDao {
#Query("select * from teams where id = :teamId")
Single<Team> getTeamById(int teamId);
}
What I have achieved is this.
private Single<List<Match>> fetchMatches(Team team) {
return matchDao.
getMatchesByTeamId(team.getId()).toObservable().
flatMapIterable(matches -> matches).
map(match -> teamDao.getTeamById(**match.getRivalId()**).toObservable() // this doesn't work ofcourse since map can't return an observable.);
}
I know I have to perhaps zip both observables , but how would I go about doing that since the second observable is dependent on the first?.
If zip would have worked on a single source , I would have been able to do a
match.setRivalTeam(team) in the zipper method.
Hints?