Skip to content

Commit 17968ef

Browse files
committed
Global rendering and logging improvements
1 parent 2db544b commit 17968ef

File tree

19 files changed

+125
-65
lines changed

19 files changed

+125
-65
lines changed

elmdroid/src/main/java/cz/inventi/elmdroid/ElmArchitecture.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ interface ComponentRuntime<STATE : State, in MSG : Msg> : DefaultLifecycleObserv
2121
override fun onDestroy(owner: LifecycleOwner) {
2222
clear()
2323
}
24+
25+
companion object {
26+
fun <STATE : State, MSG : Msg, CMD : Cmd> create(component: Component<STATE, MSG, CMD>, lifecycleOwner: LifecycleOwner? = null, logLevel: LogLevel = Elmdroid.defaultLogLevel): ComponentRuntime<STATE, MSG> {
27+
val rxRuntime = RxRuntime(component, logLevel)
28+
if (lifecycleOwner != null) {
29+
rxRuntime.bindTo(lifecycleOwner)
30+
}
31+
return rxRuntime
32+
}
33+
}
2434
}
2535

2636
/** Key class specifying all mayor pars of your elm architecture. */

elmdroid/src/main/java/cz/inventi/elmdroid/ElmViewModel.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import android.arch.lifecycle.ViewModel
66

77
open class ElmViewModel<STATE : State, in MSG : Msg, CMD : Cmd> (component: Component<STATE, MSG, CMD>, logLevel: LogLevel = LogLevel.NONE) :
88
ViewModel(),
9-
ComponentRuntime<STATE, MSG> by RuntimeFactory.create(component, logLevel = logLevel) {
9+
ComponentRuntime<STATE, MSG> by ComponentRuntime.create(component, logLevel = logLevel) {
1010

1111
override fun onCleared() {
1212
super.onCleared()
@@ -18,7 +18,7 @@ abstract class ElmBaseViewModel<STATE : State, MSG : Msg, CMD : Cmd>(logLevel: L
1818
Component<STATE, MSG, CMD>,
1919
ComponentRuntime<STATE, MSG> {
2020

21-
private val runtime = RuntimeFactory.create(this, logLevel = logLevel)
21+
private val runtime = ComponentRuntime.create(this, logLevel = logLevel)
2222

2323
override fun state(): LiveData<STATE> = runtime.state()
2424

@@ -31,7 +31,7 @@ abstract class ElmSimpleBaseViewModel<STATE : State, MSG : Msg>(logLevel: LogLev
3131
SimpleComponent<STATE, MSG>,
3232
ComponentRuntime<STATE, MSG> {
3333

34-
private val runtime = RuntimeFactory.create(this, logLevel = logLevel)
34+
private val runtime = ComponentRuntime.create(this, logLevel = logLevel)
3535

3636
override fun state(): LiveData<STATE> = runtime.state()
3737

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package cz.inventi.elmdroid
2+
3+
object Elmdroid {
4+
var defaultLogLevel = LogLevel.NONE
5+
}

elmdroid/src/main/java/cz/inventi/elmdroid/RuntimeFactory.kt

Lines changed: 0 additions & 15 deletions
This file was deleted.

elmdroid/src/main/java/cz/inventi/elmdroid/RxRuntime.kt

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package cz.inventi.elmdroid
22

33
import android.arch.lifecycle.LiveData
44
import android.arch.lifecycle.MutableLiveData
5-
import android.util.Log
65
import com.jakewharton.rxrelay2.BehaviorRelay
76
import io.reactivex.Observable
87
import io.reactivex.ObservableTransformer
@@ -44,7 +43,7 @@ internal class RxRuntime<STATE : State, in MSG : Msg, CMD : Cmd> (component: Com
4443
val subObs: Observable<MSG> = createSubObs(sub, sharedStateRelay)
4544
val subDisposable = subObs
4645
.subscribeNewObserveMain()
47-
.doOnSubscribe { log(LogLevel.FULL,"Subscribed sub: $sub") }
46+
.doOnSubscribe { log(logLevel, LogLevel.FULL, TAG,"Subscribed sub: $sub") }
4847
.subscribe { msg -> dispatch(msg) }
4948
compositeDisposable.add(subDisposable)
5049
}
@@ -54,26 +53,26 @@ internal class RxRuntime<STATE : State, in MSG : Msg, CMD : Cmd> (component: Com
5453

5554
override fun clear() {
5655
compositeDisposable.clear()
57-
log(LogLevel.BASIC, "Runtime cleared")
56+
log(logLevel, LogLevel.BASIC, TAG, "Runtime cleared")
5857
}
5958

6059
override fun dispatch(msg: MSG) {
6160
msgRelay.accept(msg)
62-
log(LogLevel.BASIC,"Msg dispatched: $msg")
61+
log(logLevel, LogLevel.BASIC, TAG,"Msg dispatched: $msg")
6362
}
6463

6564
private fun updateStateValue(stateVal: STATE) {
6665
state.value = stateVal
6766
stateRelay.accept(stateVal)
68-
log(LogLevel.BASIC, "State updated to: $stateVal")
67+
log(logLevel, LogLevel.BASIC, TAG, "State updated to: $stateVal")
6968
}
7069

7170
private fun cmdToMsg(component: Component<STATE, MSG, CMD>): ObservableTransformer<Pair<STATE, CMD?>, MSG> {
7271
return ObservableTransformer { obs ->
7372
obs.filter{ (_, maybeCmd) -> maybeCmd != null }
7473
.map { (_, cmd) -> cmd }
7574
.observeOn(Schedulers.newThread())
76-
.doOnNext { cmd -> log(LogLevel.BASIC, "Calling cmd: $cmd") }
75+
.doOnNext { cmd -> log(logLevel, LogLevel.BASIC, TAG, "Calling cmd: $cmd") }
7776
.flatMap { cmd -> component.call(cmd).toObservable()}
7877
.observeOn(AndroidSchedulers.mainThread())
7978
}
@@ -88,18 +87,15 @@ internal class RxRuntime<STATE : State, in MSG : Msg, CMD : Cmd> (component: Com
8887
is StatefulSub<STATE, MSG> -> {
8988
sharedStateRelay
9089
.distinctUntilChanged { s1, s2 -> !sub.isDistinct(s1, s2) }
91-
.doOnNext{ state -> log(LogLevel.FULL, "New state $state for StatefulSub $sub to handle")}
90+
.doOnNext{ state -> log(logLevel, LogLevel.FULL, TAG, "New state $state for StatefulSub $sub to handle")}
9291
.switchMap { state -> sub(state) }
9392
}
9493
}
9594
}
9695

97-
private fun log(
98-
minLogLevel: LogLevel,
99-
logMsg: String
100-
) {
101-
if (minLogLevel.logLevelIndex <= logLevel.logLevelIndex) {
102-
Log.d("ComponentRuntime", logMsg)
103-
}
96+
companion object {
97+
const val TAG = "ComponentRuntime"
10498
}
99+
100+
105101
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
11
package cz.inventi.elmdroid
22

3+
import android.util.Log
34
import io.reactivex.Observable
45
import io.reactivex.android.schedulers.AndroidSchedulers
56
import io.reactivex.schedulers.Schedulers
67

78
internal fun <T> Observable<T>.subscribeNewObserveMain(): Observable<T> {
89
return this.subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread())
910
}
11+
12+
internal fun log(
13+
logLevel: LogLevel,
14+
minLogLevel: LogLevel,
15+
tag: String,
16+
logMsg: String
17+
) {
18+
if (minLogLevel.logLevelIndex <= logLevel.logLevelIndex) {
19+
Log.d(tag, logMsg)
20+
}
21+
}

elmdroid/src/main/java/cz/inventi/elmdroid/ViewRenderer.kt

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ interface ViewRenderer<in V : LifecycleOwner, S: State> : Observer<S>, DefaultLi
1010
infix fun <S, T> Triple<S, S?, (S) -> T>.into(apply: (T) -> Unit): S
1111
}
1212

13-
abstract class BaseViewRenderer<in V : LifecycleOwner, S: State> (private var view: V?) : ViewRenderer<V, S> {
13+
abstract class BaseViewRenderer<in V : LifecycleOwner, S: State> (private var view: V?, private val logLevel: LogLevel = Elmdroid.defaultLogLevel) : ViewRenderer<V, S> {
1414

1515
private var previouslyRenderedState: S? = null
1616

@@ -29,19 +29,27 @@ abstract class BaseViewRenderer<in V : LifecycleOwner, S: State> (private var vi
2929

3030
override fun onDestroy(owner: LifecycleOwner) {
3131
view = null
32+
log(logLevel, LogLevel.BASIC, TAG, "onDestroy: view deleted" )
3233
}
3334

3435
override fun onStop(owner: LifecycleOwner) {
3536
previouslyRenderedState = null
37+
log(logLevel, LogLevel.BASIC, TAG, "onStop: previouslyRenderedState deleted" )
3638
}
3739

3840
override infix fun <T> S.from(getter: (S) -> T): Triple<S, S?, (S) -> T> = Triple(this, previouslyRenderedState, getter)
3941
override infix fun <S, T> Triple<S, S?, (S) -> T>.into(apply: (T) -> Unit): S {
4042
val (state, prevState, getter) = this
4143
val newValue = getter(state)
42-
if (prevState == null || getter(prevState) != newValue) {
44+
val oldValue = prevState?.let { getter(prevState) }
45+
if (oldValue == null || oldValue != newValue) {
4346
apply(newValue)
47+
log(logLevel, LogLevel.FULL, TAG, "New value applied. From $oldValue => $newValue" )
4448
}
4549
return state
4650
}
51+
52+
companion object {
53+
const val TAG = "ViewRenderer"
54+
}
4755
}

elmdroid/src/test/java/cz/inventi/elmdroid/ComponentRuntimeTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class ComponentRuntimeTest {
3838
MockitoAnnotations.initMocks(this)
3939
`when`(component.initState()).thenReturn(TestState(3, "init"))
4040
lifecycleOwner = TestLifecycleOwner()
41-
runtime = Mockito.spy(RuntimeFactory.create(component))
41+
runtime = Mockito.spy(ComponentRuntime.create(component))
4242
runtime.bindTo(lifecycleOwner)
4343
}
4444

sample/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ dependencies {
3333

3434
// arch
3535
implementation deps.lifecycle.viewmodel
36-
implementation deps.lifecycle.livedata
36+
implementation deps.lifecycle.extensions
3737
implementation deps.lifecycle.java8
3838

3939
// rx
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
package com.example.elmdroid
22

33
import android.app.Application
4+
import cz.inventi.elmdroid.Elmdroid
45
import cz.inventi.elmdroid.LogLevel
5-
import cz.inventi.elmdroid.RuntimeFactory
66

77

88
class ElmApp : Application() {
99
override fun onCreate() {
1010
super.onCreate()
11-
RuntimeFactory.defaultLogLevel = if (BuildConfig.DEBUG) LogLevel.FULL else LogLevel.NONE
11+
Elmdroid.defaultLogLevel = if (BuildConfig.DEBUG) LogLevel.FULL else LogLevel.NONE
1212
}
1313
}

0 commit comments

Comments
 (0)