diff --git a/README.md b/README.md index d964ac8..fd0ac4b 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,6 @@ and: ```gradle dependencies { - implementation "cc.femto:kommon-mvi:1.0.0" + implementation "cc.femto:kommon-mvi:2.1.0" } ``` diff --git a/build.gradle b/build.gradle index 74ad192..1194eb1 100644 --- a/build.gradle +++ b/build.gradle @@ -2,9 +2,8 @@ buildscript { ext.gradle_version = '3.0.1' - ext.kotlin_version = '1.2.10' + ext.kotlin_version = '1.2.41' ext.rxjava_version = '2.1.7' - ext.rxandroid_version = '2.0.1' repositories { google() diff --git a/mvi/build.gradle b/mvi/build.gradle index 071b33e..237bb50 100644 --- a/mvi/build.gradle +++ b/mvi/build.gradle @@ -14,14 +14,14 @@ buildscript { } android { - compileSdkVersion 26 - buildToolsVersion "26.0.2" + compileSdkVersion 27 + buildToolsVersion "27.0.3" defaultConfig { minSdkVersion 16 - targetSdkVersion 26 - versionCode 3 - versionName "2.0.1" + targetSdkVersion 27 + versionCode 4 + versionName "2.1.0" } buildTypes { release { @@ -37,7 +37,6 @@ android { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxjava_version" - implementation "io.reactivex.rxjava2:rxandroid:$rxandroid_version" } task sourcesJar(type: Jar) { diff --git a/mvi/src/main/kotlin/cc/femto/kommon/mvi/BaseModel.kt b/mvi/src/main/kotlin/cc/femto/kommon/mvi/BaseModel.kt index 9f18441..120f60d 100644 --- a/mvi/src/main/kotlin/cc/femto/kommon/mvi/BaseModel.kt +++ b/mvi/src/main/kotlin/cc/femto/kommon/mvi/BaseModel.kt @@ -1,7 +1,6 @@ package cc.femto.kommon.mvi import io.reactivex.Observable -import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable import io.reactivex.subjects.BehaviorSubject import io.reactivex.subjects.PublishSubject @@ -11,21 +10,47 @@ abstract class BaseModel : Model = BehaviorSubject.create() protected val actions: PublishSubject = PublishSubject.create() + private val events: PublishSubject = PublishSubject.create() - override fun viewModel(): Observable = viewModel.observeOn(AndroidSchedulers.mainThread()) + override fun viewModel(): Observable = viewModel - override fun actions(): Observable = actions.observeOn(AndroidSchedulers.mainThread()) + override fun actions(): Observable = actions override fun detach() { disposables.clear() } - protected fun makeViewModel(events: Observable, initialViewModel: VM, reducer: (VM, T) -> VM) { - disposables.add(events.scan(initialViewModel, reducer) + /** + * Exposes the internal [Event] stream that passes through the reducer + */ + protected fun events(): Observable = events + + /** + * Dispatch an event to the reducer + */ + fun dispatchEvent(event: Event) = events.onNext(event) + + /** + * Dispatch to set the current view model, e.g. when testing + */ + fun dispatchViewModel(viewModel: VM) { + this.viewModel.onNext(viewModel) + } + + /** + * Subscribes internal event relay to supplied event stream and sets up [viewModel] + */ + protected fun makeViewModel(events: Observable, initialViewModel: VM, reducer: (VM, Event) -> VM) { + disposables.add(this.events + .scan(initialViewModel, reducer) .distinctUntilChanged() .subscribe(viewModel::onNext)) + disposables.add(events.subscribe(this.events::onNext)) } + /** + * Subscribes internal action relay to supplied action stream and sets up [actions] + */ protected fun makeActions(actions: Observable) { disposables.add(actions.subscribe(this.actions::onNext)) } diff --git a/mvi/src/main/kotlin/cc/femto/kommon/mvi/Model.kt b/mvi/src/main/kotlin/cc/femto/kommon/mvi/Model.kt index ead1013..40e4f5a 100644 --- a/mvi/src/main/kotlin/cc/femto/kommon/mvi/Model.kt +++ b/mvi/src/main/kotlin/cc/femto/kommon/mvi/Model.kt @@ -12,7 +12,10 @@ interface Model { * * override fun onCreate(savedInstanceState: Bundle?) { * super.onCreate(savedInstanceState) - * view.attach(model.viewModel(), model.actions()) + * view.attach( + * model.viewModel().observeOn(AndroidSchedulers.mainThread()), + * model.actions().observeOn(AndroidSchedulers.mainThread()) + * ) * model.attach(view.intents()) * } * @@ -32,6 +35,15 @@ interface Model { */ fun detach() + /** + * ViewModel stream + * + * NB: Observe on main thread + */ fun viewModel(): Observable + + /** + * Actions stream + */ fun actions(): Observable }