From eb32192b34d449dc5318da09b34284525d083c79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B0=D0=BA=D1=81=D0=B8=D0=BC=20=D0=91=D0=B0=D1=87?= =?UTF-8?q?=D0=B8=D0=BD=D1=81=D0=BA=D0=B8=D0=B8=CC=86?= Date: Tue, 22 Sep 2020 11:38:10 +0300 Subject: [PATCH] added mediators for logging --- mvi-arch/build.gradle | 3 ++ .../roboswag/mvi_arch/core/MviViewModel.kt | 31 +++++++++++- .../touchin/roboswag/mvi_arch/core/Store.kt | 13 +++++ .../mvi_arch/mediator/LoggingMediator.kt | 49 +++++++++++++++++++ .../roboswag/mvi_arch/mediator/Mediator.kt | 18 +++++++ .../mvi_arch/mediator/MediatorStore.kt | 25 ++++++++++ 6 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 mvi-arch/src/main/java/ru/touchin/roboswag/mvi_arch/mediator/LoggingMediator.kt create mode 100644 mvi-arch/src/main/java/ru/touchin/roboswag/mvi_arch/mediator/Mediator.kt create mode 100644 mvi-arch/src/main/java/ru/touchin/roboswag/mvi_arch/mediator/MediatorStore.kt diff --git a/mvi-arch/build.gradle b/mvi-arch/build.gradle index b115592..6059357 100644 --- a/mvi-arch/build.gradle +++ b/mvi-arch/build.gradle @@ -5,6 +5,7 @@ dependencies { implementation project(":navigation-base") implementation project(":lifecycle") implementation project(":kotlin-extensions") + implementation project(":logging") implementation("androidx.core:core-ktx") implementation("androidx.appcompat:appcompat") @@ -23,6 +24,8 @@ dependencies { implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android") + implementation("com.tylerthrailkill.helpers:pretty-print:2.0.2") + def fragmentVersion = "1.2.1" def lifecycleVersion = "2.2.0" def coroutinesVersion = "1.3.7" diff --git a/mvi-arch/src/main/java/ru/touchin/roboswag/mvi_arch/core/MviViewModel.kt b/mvi-arch/src/main/java/ru/touchin/roboswag/mvi_arch/core/MviViewModel.kt index d3df82c..a04d309 100644 --- a/mvi-arch/src/main/java/ru/touchin/roboswag/mvi_arch/core/MviViewModel.kt +++ b/mvi-arch/src/main/java/ru/touchin/roboswag/mvi_arch/core/MviViewModel.kt @@ -1,12 +1,19 @@ package ru.touchin.roboswag.mvi_arch.core import android.os.Parcelable +import androidx.annotation.CallSuper import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.Observer import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.Transformations import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.launch +import ru.touchin.mvi_arch.BuildConfig import ru.touchin.roboswag.mvi_arch.marker.ViewAction import ru.touchin.roboswag.mvi_arch.marker.ViewState +import ru.touchin.roboswag.mvi_arch.mediator.LoggingMediator +import ru.touchin.roboswag.mvi_arch.mediator.MediatorStore /** * Base [ViewModel] to use in MVI architecture. @@ -33,6 +40,12 @@ abstract class MviViewModel(mediatorStore::onNewState) + + init { + viewModelScope.launch { + state.observeForever(stateMediatorObserver) + } + } + + @CallSuper + open fun dispatchAction(action: Action) { + mediatorStore.onAction(action) + } + + override fun onCleared() { + super.onCleared() + state.removeObserver(stateMediatorObserver) + } } diff --git a/mvi-arch/src/main/java/ru/touchin/roboswag/mvi_arch/core/Store.kt b/mvi-arch/src/main/java/ru/touchin/roboswag/mvi_arch/core/Store.kt index 56eef64..5655d64 100644 --- a/mvi-arch/src/main/java/ru/touchin/roboswag/mvi_arch/core/Store.kt +++ b/mvi-arch/src/main/java/ru/touchin/roboswag/mvi_arch/core/Store.kt @@ -14,9 +14,12 @@ import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch +import ru.touchin.mvi_arch.BuildConfig import ru.touchin.roboswag.mvi_arch.marker.SideEffect import ru.touchin.roboswag.mvi_arch.marker.StateChange import ru.touchin.roboswag.mvi_arch.marker.ViewState +import ru.touchin.roboswag.mvi_arch.mediator.LoggingMediator +import ru.touchin.roboswag.mvi_arch.mediator.MediatorStore abstract class Store( initialState: State @@ -32,6 +35,12 @@ abstract class Store> = mutableListOf() + private val mediatorStore = MediatorStore( + listOfNotNull( + LoggingMediator(this::class.simpleName!!).takeIf { BuildConfig.DEBUG } + ) + ) + init { storeScope.launch { effects @@ -43,10 +52,13 @@ abstract class Store @@ -55,6 +67,7 @@ abstract class Store logObject( + prefix: String, + obj: T + ) { + val builder = StringBuilder() + pp(obj = obj, writeTo = builder) + + val prettyOutput = builder.toString() + Lc.d("$objectName: $prefix$prettyOutput\n") + } +} diff --git a/mvi-arch/src/main/java/ru/touchin/roboswag/mvi_arch/mediator/Mediator.kt b/mvi-arch/src/main/java/ru/touchin/roboswag/mvi_arch/mediator/Mediator.kt new file mode 100644 index 0000000..699b3ba --- /dev/null +++ b/mvi-arch/src/main/java/ru/touchin/roboswag/mvi_arch/mediator/Mediator.kt @@ -0,0 +1,18 @@ +package ru.touchin.roboswag.mvi_arch.mediator + +import ru.touchin.roboswag.mvi_arch.marker.SideEffect +import ru.touchin.roboswag.mvi_arch.marker.StateChange +import ru.touchin.roboswag.mvi_arch.marker.ViewAction +import ru.touchin.roboswag.mvi_arch.marker.ViewState + +interface Mediator { + + fun onEffect(effect: SideEffect) + + fun onAction(action: ViewAction) + + fun onNewState(state: ViewState) + + fun onStateChange(change: StateChange) + +} diff --git a/mvi-arch/src/main/java/ru/touchin/roboswag/mvi_arch/mediator/MediatorStore.kt b/mvi-arch/src/main/java/ru/touchin/roboswag/mvi_arch/mediator/MediatorStore.kt new file mode 100644 index 0000000..70ede8d --- /dev/null +++ b/mvi-arch/src/main/java/ru/touchin/roboswag/mvi_arch/mediator/MediatorStore.kt @@ -0,0 +1,25 @@ +package ru.touchin.roboswag.mvi_arch.mediator + +import ru.touchin.roboswag.mvi_arch.marker.SideEffect +import ru.touchin.roboswag.mvi_arch.marker.StateChange +import ru.touchin.roboswag.mvi_arch.marker.ViewAction +import ru.touchin.roboswag.mvi_arch.marker.ViewState + +class MediatorStore(private val mediators: List) : Mediator { + + override fun onAction(action: ViewAction) { + mediators.forEach { it.onAction(action) } + } + + override fun onEffect(effect: SideEffect) { + mediators.forEach { it.onEffect(effect) } + } + + override fun onNewState(state: ViewState) { + mediators.forEach { it.onNewState(state) } + } + + override fun onStateChange(change: StateChange) { + mediators.forEach { it.onStateChange(change) } + } +}