Given
@GenerateReducingImplementation(
baseClass = SerialReactiveModel::class,
lceState = LceState::class
)
interface SampleModel {
fun fetchMovieList(userId: String)
fun fetchMovieListState(): Observable<LceState<List<Movie>>>
fun saveMovieRating(userId: String, movieId: String)
fun saveMovieRatingState(): Observable<LceState<Unit>>
fun movieGenreList(): Observable<List<Genre>>
}
this processor will generate this model implementation.
It will be based on an interface SampleModelOperations
which is also generated for you to implement:
// Generated by processor
interface SampleModelOperations {
fun createFetchMovieListOperation(userId: String, state: SampleModelImpl.State): Single<LceState<List<Movie>>>
fun createSaveMovieRating(userId: String, movieId: String, state: SampleModelImpl.State): Completable
fun movieGenreList(): Observable<List<Genre>>
}
Reactive properties are recognized based on the returned LCE state type. To tell the processor about this type you'll need to provide it with a factory which knows how to create instances of LCE state:
data class LceState<C>(
val isLoading: Boolean,
val content: C?,
val error: Throwable?
)
class LceStateFactoryImpl : LceStateFactory<LceState<*>> {
override fun createLceContent(content: Any): LceState<*> {
return LceState(isLoading = false, content = content, error = null)
}
override fun createLceError(error: Any): LceState<*> {
return LceState(isLoading = false, content = null, error = error as Throwable)
}
override fun createLceLoading(): LceState<*> {
return LceState(isLoading = true, content = content, error = null)
}
}
After processor knows about LCE state type, it will search for reactive getters — functions with return type Observable<LceState<*>>
, and then attempt to find matching "request"-functions by removing State
suffix from getter name. For example: getter saveMovieRatingState
should have request named saveMovieRating
to be found by processor.
All methods of the model interface which are not recognized as reactive getters/requests will be copied to generated operations
-interface without any changes (see movieGenreList()
in the above example)
To create an instance of the model which uses the generated implementation call:
val operationsImpl = object : SampleModelOperations {
// Tyour implementation
}
val lceStateFactory = LceStateFactoryImpl()
val model = ModelGenerator.createModel(operationsImpl, lceStateFactory)
model.fetchMovieListState().subscribe({ println("Got list $it") })
model.fetchMovieList("my-user-id")
Add a Gradle dependency:
apply plugin: 'kotlin-kapt'
implementation 'com.github.dimsuz:etg-model-generator-runtime:1.0.0-RC5'
kapt 'com.github.dimsuz:etg-model-generator-processor:1.0.0-RC5'
Copyright 2019 Dmitry Suzdalev
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.