motorro / rxlcemodel Goto Github PK
View Code? Open in Web Editor NEWAn Android library for data load with cache and loading state
License: Apache License 2.0
An Android library for data load with cache and loading state
License: Apache License 2.0
Implement base compose view component as a separate artifact
Sometimes you need to refresh data on subscription.
Make available flat-mapping the Lce state.
Like:
val s1:LceState<Int> = LceState.Content(1, true)
val s2:LceState<String> = s1.flatMap { a: Int -> LceState.Content("a = $a", true) }
Simplify boilerplate in cache module.
Create common delegate factories
When DiskLRU delegate fails to serialize data the error is swallowed and model does not get any data as subsequent read is always null
DiskLru cache uses 120-symbol (64 in a released 2.0.2) a-zA-Z0-9-_
cache keys which may not be enough for some scenarios. One may hash original parameters but clashing takes place in that case. Need some double-check of caching parameters when reading to avoid returning wrong data
In case there are multiple cache subscribers for the same cache like this:
/**
* Creates double model that is bound to the same cache service with different params
*/
private fun createDoubleModel(): Observable<LceState<Pair<TestData, TestData>>> {
val model1 = LceModel.cacheThenNet(1, netService, cacheService, Observable.empty())
.state
.subscribeOn(Schedulers.io())
val model2 = LceModel.cacheThenNet(2, netService, cacheService, Observable.empty())
.state
.subscribeOn(Schedulers.io())
return Observable.combineLatest(model1, model2) { dataState1, dataState2 ->
dataState1.combine(dataState2) { data1, data2 ->
data1 ?: return@combine null
data2 ?: return@combine null
data1 to data2
}
}
}
If you invalidate cache while a load operation is in progress one of models stops to respond to cache invalidation.
Some of Lce consumers don't care about parameter that load data
Extract a state and refresh from lcemodel to base interface
Change to cacheThenNet
Implement base view model components to work with LCE as a separate artifact
Need to bypass cancellation errors as-as not mapping them to LCE errors
Use this recipe
Build a coroutines port of LceModel
Similar to onEmptyLoadingReturn
create a function to update a data
Implement base view component to handle LCE data as a separate artifact
There are situations when LceModel
is created internally in some Rx mappings: transformations, pagination, etc. The refresh
action is unavailable to the outside world in this case.
Write a helper function that takes a refresh event stream and returns the model state emission like:
val refresh = PublishSubject.create()
val model = LceModel.cacheThenNet(...)
val data: Observable<LceState<...>> = model.withRefreshStream(refresh)
Build docs with github action instead of Travis, since Maven publish doesn't work there
script: "./gradlew displayVersion dokkaGfmMultimodule --no-daemon"
Consider a cache service with complex internal structure that is updated by some internal logic.
For example a database that saves entities and something that updates records' internal structure.
In case of Room you may observe a query and get updates if something changes underneath. But sometimes you have a complex entity with relations that are not so easy to fetch as they need conditional processing in synchronous way.
In this case you may write an SQL delegate for sync-delegate service to implement reactive cache with updates.
When you get/put the whole entity the solution works. But as soon as you start to update entity parts you need some way to notify subscribers of data change.
it would be convenient if there were a mapping function to return lce error in case mapper fails:
@Test
fun catchesErrorToLce() {
val error = IllegalArgumentException("error")
val state1 = LceState.Content(1, true)
val state2 = state1.catchToLce<Int, Int> { throw error }
assertEquals(
LceState.Error(null, false, error),
state2
)
}
Make the initial loading state emission optional
(Test ticket to check Travis workflow)
Having a flow of LceState<Int>
I need to get an async result for each data value like LceState<DataLoadedForOriginalInt>
.
Make a mapping function similar to Observable.flatMapSingle
Sometimes it is handy to combine several Lce states.
Write a function that combines state and data with a mapper.
The transformation matrix should be the following:
Receiver | other | Result |
---|---|---|
Loading | Loading | Loading |
Loading | Content | Loading |
Loading | Error | Error |
Loading | Terminated | Terminated |
Content | Loading | Loading |
Content | Content | Content* |
Content | Error | Error |
Content | Terminated | Terminated |
Error | Loading | Error |
Error | Content | Error |
Error | Error | Error |
Error | Terminated | Terminated |
Terminated | Loading | Terminated |
Terminated | Content | Terminated |
Terminated | Error | Terminated |
Terminated | Terminated | Terminated |
Loading
Passing PARAMS through LCE states seems to be a bad architectural decision.
It makes hard to maintain PARAMS flow if you have a compex assembly - params stream may not be available on time of preloading.
Like you use a current user as a param, but the user is not available from the beginning (should be fetched from user manager of some kind).
Thus a better approach is to return params back along with data in the same data structure.
Since this is a breaking change - increment major version
Implement cache delegate serializer for Kotlin serialization
CacheDelegateSerializerDeserializer
Expected: Model should update
Actual: No update and refresh
Problem: mutable validity status in lifespan. Need an immutable snapshot of validity from cache
Update library for Rx3
Fix including module index files
In some cases the Lce flow represents a finite number of events, or the error is fatal and no more events are following without complete resubscription. One can send a termination event or process the observable onComplete to handle this situation.
However sometimes knowing that the other (Content, Error) state is final may be easier to process by UI. For example if some fatal error occures within subscription it is easier to process error knowing the event is final and we should resubscribe from scratch rather then wait and process Terminated while UI is in error state. Also one can't possibly tell if Terminated is following any fatal error.
Thus indicating the state change is final by flag of some kind can make state processing easier.
It is more convenient if any observable may be used as a refresh stream in LceUseCase.withRefresh
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.