Im new with Rxjava on Android Project, here my code
class RadioListRepositoryImpl(private val apiServices: ApiServices, private val chlDao: ChannelDao) : RadioListRepository {
private val results: MutableList<DataResponse>
init {
results = ArrayList<DataResponse>()
}
override fun getData(): Observable<DataResponse> {
return dataFromMemory().switchIfEmpty(dataFromNetwork())
}
override fun dataFromMemory(): Observable<DataResponse> {
val cacheDateExp = DateTime().minusHours(6)
if(chlDao.isCacheExpired(cacheDateExp).isNotEmpty()){
Logger.d("Get data from cache SQLITE")
val chList: MutableList<DataResponse> = ArrayList()
val cache = chlDao.loadAll()
repeat(cache.size){ i ->
val ch = DataResponse()
ch.channelId = cache[i].channelId
ch.channelTitle = cache[i].title
chList.add(ch)
}
return Observable.from(chList)
}else{
chlDao.deleteAll()
return Observable.empty<DataResponse>()
}
}
override fun dataFromNetwork(): Observable<DataResponse> {
val dttime = DateTime()
return apiServices.getChannelList()
.concatMap {
dataListResponseModel -> Observable.from(dataListResponseModel.radio)
}
.doOnNext {
channelDataResponse -> results.add(channelDataResponse)
}
.doOnNext { channelDataResponse ->
Logger.d("Put data to cache")
val c: ChannelEntitiy = ChannelEntitiy()
c.channelId = channelDataResponse.channelId
c.title = channelDataResponse.channelTitle
chlDao.insert(c)
}
}
}
My other class access method getData() and I want if data is empty from memory (sqlite) then get data from network.
But what I want is if data is empty from memory then get data from network insert to memory and after that getData() method return dataFromMemory()
Can I handle it using another Rx operator to simplify my code ?
答案 0 :(得分:1)
When you want to get data from multi-sources, concat
and first
should suit for you.
// Our sources (left as an exercise for the reader)
Observable<Data> memory = ...;
Observable<Data> disk = ...;
Observable<Data> network = ...;
// Retrieve the first source with data
Observable<Data> source = Observable
.concat(memory, disk, network)
.first();
concat()
takes multiple Observables
and concatenates their sequences. first()
emits only the first item from a sequence. Therefore, if you use concat().first()
, it retrieves the first item emitted by multiple sources.
The key to this pattern is that concat()
only subscribes to each child Observable when it needs to. There's no unnecessary querying of slower sources if data is cached, since first()
will stop the sequence early. In other words, if memory returns a result, then we won't bother going to disk or network. Conversely, if neither memory nor disk have data, it'll make a new network request.
Note that the order of the source Observables
in concat()
matters, since it's checking them one-by-one.
Then if you want to save data for each sources, just change a little bit it your source with doOnNext()
Observable<Data> networkWithSave = network.doOnNext(data -> {
saveToDisk(data);
cacheInMemory(data);
});
Observable<Data> diskWithCache = disk.doOnNext(data -> {
cacheInMemory(data);
});