My view model is subscribing KeywordLocalDataSource#readCurrent. I expected that calling Realm#copyToRealmOrUpdate emits new(stored) object.
RealmQuery.findFirstAsync().asFlowable() will emit newly saved object (by Realm#copyToRealmOrUpdate)
No new value emitted.
class KeywordDataRepository @Inject constructor() : KeywordRepository {
@Inject
lateinit var localDataSource: KeywordLocal
@Inject
lateinit var remoteDataSource: KeywordRemote
override fun readCurrent(): Flowable<Keyword> {
remoteDataSource
.readCurrent()
.subscribe(
localDataSource::save,
Throwable::printStackTrace
)
return localDataSource.readCurrent()
}
}
class KeywordLocalDataSource @Inject constructor(
val realmProvider: Provider<Realm>
) : KeywordLocal {
override fun save(keyword: Keyword) {
realmProvider.get()
.executeTransactionAsync {
val entity = KeywordMapper.toEntity(keyword)
it.copyToRealmOrUpdate(entity)
}
}
override fun readCurrent(): Flowable<Keyword> {
val current = Calendar.getInstance().time
return realmProvider.get()
.where(KeywordEntity::class.java)
.lessThanOrEqualTo("activatedAt", current)
.sort("id", Sort.DESCENDING)
.findFirstAsync()
.asFlowable<KeywordEntity>()
.filter(RealmObject::isValid)
.map(KeywordMapper::fromEntity)
}
}
KeywordDataRepository#readCurrent method returns KeywordLocalDataSource#readCurrent. I expected that after KeywordRemote#readCurrent succeeds, it will save new object to Realm database, then Realm emits new object. But no value emitted.
Realm version(s): 4.3.3
Realm sync feature enabled: no
Android Studio version: 3.0.1
Which Android version and device: Nexus 5 API 27
It won't emit an object that won't exist, and won't continue looking for a new one if it doesn't yet exist either.
This behavior was changed in 3.1.0:
findFirstAsync() now returns an invalid object if there is no object matches the query condition instead of running the query repeatedly until it can find one (https://github.com/realm/realm-java/issues/4352).
The tricky thing is that until findFirstAsync returns some kind of RealmOptional<T>, if you ask me, it'll always be wonky 馃槃 I've never found a good use-case for it. None!
Anyways, you should just use
.where(KeywordEntity::class.java)
.lessThanOrEqualTo("activatedAt", current)
.sort("id", Sort.DESCENDING)
.findAllAsync() // <--- !!
.asFlowable<KeywordEntity>()
.filter { results -> results.isValid() && results.isLoaded() && !results.isEmpty() }
.map { results -> results.first() } // <-- !!!
.map(KeywordMapper::fromEntity)
Or something like that.
Thank you for your help!
My first approach was this,
Flowable.create({ emitter: FlowableEmitter<Keyword> ->
realmProvider.get()
.where(KeywordEntity::class.java)
.lessThanOrEqualTo("activatedAt", current)
.sort("id", Sort.DESCENDING)
.findAllAsync()
.addChangeListener { entities ->
if (entities.size > 0)
emitter.onNext(KeywordMapper.fromEntity(entities.first()!!))
}
}, BackpressureStrategy.LATEST)
but seems your solution is more pretty :)
Most helpful comment
It won't emit an object that won't exist, and won't continue looking for a new one if it doesn't yet exist either.
This behavior was changed in 3.1.0:
The tricky thing is that until
findFirstAsyncreturns some kind ofRealmOptional<T>, if you ask me, it'll always be wonky 馃槃 I've never found a good use-case for it. None!Anyways, you should just use
Or something like that.