Skip to content

Commit f453cc1

Browse files
committed
Binder implementation
1 parent 9237883 commit f453cc1

File tree

11 files changed

+296
-136
lines changed

11 files changed

+296
-136
lines changed

mvicore-base/src/commonMain/kotlin/com/badoo/mvicore/common/binder/Binder.kt

+62-3
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,26 @@ import com.badoo.mvicore.common.Cancellable
44
import com.badoo.mvicore.common.Sink
55
import com.badoo.mvicore.common.Source
66
import com.badoo.mvicore.common.lifecycle.Lifecycle
7+
import com.badoo.mvicore.common.lifecycle.Lifecycle.Event.BEGIN
8+
import com.badoo.mvicore.common.lifecycle.Lifecycle.Event.END
79

8-
class Binder(private val lifecycle: Lifecycle? = null): Cancellable {
10+
interface Binder : Cancellable {
11+
fun <T> bind(connection: Pair<Source<T>, Sink<T>>)
12+
fun <Out, In> bind(connection: Connection<Out, In>)
13+
}
14+
15+
fun Binder(): Binder = SimpleBinder()
16+
fun Binder(lifecycle: Lifecycle): Binder = LifecycleBinder(lifecycle)
17+
18+
internal class SimpleBinder : Binder {
919
private val cancellables = mutableListOf<Cancellable>()
1020

11-
fun <T> bind(connection: Pair<Source<T>, Sink<T>>) {
21+
override fun <T> bind(connection: Pair<Source<T>, Sink<T>>) {
1222
val (from, to) = connection
1323
bind(Connection(from = from, to = to))
1424
}
1525

16-
fun <Out, In> bind(connection: Connection<Out, In>) {
26+
override fun <Out, In> bind(connection: Connection<Out, In>) {
1727
val out = connection.connector?.let { it(connection.from!!) } ?: (connection.from as Source<In>)
1828
cancellables += out.connect(connection.to)
1929
}
@@ -23,3 +33,52 @@ class Binder(private val lifecycle: Lifecycle? = null): Cancellable {
2333
cancellables.clear()
2434
}
2535
}
36+
37+
internal class LifecycleBinder(private val lifecycle: Lifecycle) : Binder {
38+
private var lifecycleActive = false
39+
private val cancellables = mutableListOf<Cancellable>()
40+
private val innerBinder = SimpleBinder()
41+
private val connections = mutableListOf<Connection<*, *>>()
42+
43+
init {
44+
cancellables += lifecycle.connect {
45+
when (it) {
46+
BEGIN -> connect()
47+
END -> disconnect()
48+
}
49+
}
50+
cancellables += innerBinder
51+
}
52+
53+
override fun <T> bind(connection: Pair<Source<T>, Sink<T>>) {
54+
val (from, to) = connection
55+
bind(Connection(from = from, to = to))
56+
}
57+
58+
override fun <Out, In> bind(connection: Connection<Out, In>) {
59+
connections += connection
60+
if (lifecycleActive) {
61+
innerBinder.bind(connection)
62+
}
63+
}
64+
65+
private fun connect() {
66+
if (lifecycleActive) return
67+
68+
lifecycleActive = true
69+
connections.forEach { innerBinder.bind(it) }
70+
}
71+
72+
private fun disconnect() {
73+
if (!lifecycleActive) return
74+
75+
lifecycleActive = false
76+
innerBinder.cancel()
77+
}
78+
79+
override fun cancel() {
80+
cancellables.forEach { it.cancel() }
81+
connections.clear()
82+
}
83+
84+
}

mvicore-base/src/commonMain/kotlin/com/badoo/mvicore/common/element/ActorReducerFeature.kt

-37
This file was deleted.

mvicore-base/src/commonMain/kotlin/com/badoo/mvicore/common/element/BaseFeature.kt

-46
This file was deleted.

mvicore-base/src/commonMain/kotlin/com/badoo/mvicore/common/element/ReducerFeature.kt

-38
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.badoo.mvicore.common.element
22

33
import com.badoo.mvicore.common.Cancellable
4-
import com.badoo.mvicore.common.Sink
54
import com.badoo.mvicore.common.Source
65

76
typealias Bootstrapper<Action> = () -> Source<out Action>
@@ -10,8 +9,10 @@ typealias Actor<State, Wish, Effect> = (state: State, wish: Wish) -> Source<out
109

1110
typealias Reducer<State, Effect> = (state: State, effect: Effect) -> State
1211

13-
typealias NewsPublisher<Wish, State, Effect, News> = (old: State, wish: Wish, effect: Effect, new: State) -> News?
12+
typealias NewsPublisher<Action, Effect, State, News> = (old: State, action: Action, effect: Effect, new: State) -> News?
1413

15-
interface Feature<Wish, State, News>: Sink<Wish>, Source<State>, Cancellable {
14+
typealias PostProcessor<Action, Effect, State> = (old: State, action: Action, effect: Effect, new: State) -> Action?
15+
16+
interface Feature<Wish, State, News>: (Wish) -> Unit, Source<State>, Cancellable {
1617
val news: Source<News>
1718
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.badoo.mvicore.common.feature
2+
3+
import com.badoo.mvicore.common.element.Actor
4+
import com.badoo.mvicore.common.element.Bootstrapper
5+
import com.badoo.mvicore.common.element.NewsPublisher
6+
import com.badoo.mvicore.common.element.Reducer
7+
8+
open class ActorReducerFeature<Wish : Any, Effect : Any, State : Any, News : Any>(
9+
initialState: State,
10+
bootstrapper: Bootstrapper<Wish>? = null,
11+
actor: Actor<State, Wish, Effect>,
12+
reducer: Reducer<State, Effect>,
13+
newsPublisher: NewsPublisher<Wish, Effect, State, News>? = null
14+
) : BaseFeature<Wish, Wish, Effect, State, News>(
15+
initialState = initialState,
16+
bootstrapper = bootstrapper,
17+
wishToAction = { it },
18+
actor = actor,
19+
reducer = reducer,
20+
newsPublisher = newsPublisher
21+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.badoo.mvicore.common.feature
2+
3+
import com.badoo.mvicore.common.Sink
4+
import com.badoo.mvicore.common.Source
5+
import com.badoo.mvicore.common.element.Actor
6+
import com.badoo.mvicore.common.element.Bootstrapper
7+
import com.badoo.mvicore.common.element.Feature
8+
import com.badoo.mvicore.common.element.NewsPublisher
9+
import com.badoo.mvicore.common.element.PostProcessor
10+
import com.badoo.mvicore.common.element.Reducer
11+
import com.badoo.mvicore.common.source
12+
13+
open class BaseFeature<Action : Any, Wish : Any, Effect : Any, State : Any, News : Any> (
14+
initialState: State,
15+
private val bootstrapper: Bootstrapper<Action>? = null,
16+
private val wishToAction: (Wish) -> Action,
17+
private val actor: Actor<State, Action, Effect>,
18+
private val reducer: Reducer<State, Effect>,
19+
private val newsPublisher: NewsPublisher<Action, Effect, State, News>? = null,
20+
private val postProcessor: PostProcessor<Action, Effect, State>? = null
21+
): Feature<Wish, State, News> {
22+
private val actionSource = source<Action>()
23+
internal val effectSource = source<Effect>()
24+
private val stateSource = source(initialState)
25+
private val newsSource = source<News>()
26+
27+
init {
28+
bootstrapper?.invoke()?.connect(actionSource)
29+
actionSource.connect { action ->
30+
val oldState = state
31+
actor.invoke(oldState, action)
32+
.connect { effect ->
33+
val newState = reducer(this.state, effect)
34+
stateSource(newState)
35+
newsPublisher?.invoke(oldState, action, effect, newState)?.let {
36+
newsSource(it)
37+
}
38+
postProcessor?.invoke(oldState, action, effect, newState)?.let(actionSource::invoke)
39+
}
40+
}
41+
}
42+
43+
override fun invoke(wish: Wish) {
44+
val action = wishToAction(wish)
45+
actionSource.invoke(action)
46+
}
47+
48+
override fun connect(sink: Sink<State>) = stateSource.connect(sink)
49+
50+
override fun cancel() {
51+
// TODO
52+
}
53+
54+
val state: State
55+
get() = stateSource.value!!
56+
57+
override val news: Source<News>
58+
get() = newsSource
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.badoo.mvicore.common.feature
2+
3+
//open class ReducerFeature<Wish : Any, State : Any, News : Any>(
4+
// initialState: State,
5+
// bootstrapper: Bootstrapper<Wish>? = null,
6+
// private val reducer: Reducer<State, Wish>,
7+
// private val newsPublisher: SimpleNewsPublisher<State, Wish, News>? = null
8+
//) : ActorReducerFeature<Wish, Wish, State, News>(
9+
// actor = { }
10+
//)
11+
12+
typealias SimpleNewsPublisher<State, Wish, News> = (old: State, wish: Wish, state: State) -> News?

mvicore-base/src/commonMain/kotlin/com/badoo/mvicore/common/lifecycle/lifecycle.kt

+6-3
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,20 @@ import com.badoo.mvicore.common.SimpleSource
44
import com.badoo.mvicore.common.Source
55
import com.badoo.mvicore.common.lifecycle.Lifecycle.Event.BEGIN
66
import com.badoo.mvicore.common.lifecycle.Lifecycle.Event.END
7-
import com.badoo.mvicore.common.source
87

98
interface Lifecycle : Source<Lifecycle.Event> {
109
enum class Event {
1110
BEGIN, END
1211
}
1312

14-
fun manual() = ManualLifecycle()
13+
companion object {
14+
fun manual() = ManualLifecycle()
15+
}
1516
}
1617

17-
class ManualLifecycle(private val source: SimpleSource<Lifecycle.Event> = source()) : Lifecycle, Source<Lifecycle.Event> by source {
18+
class ManualLifecycle(
19+
private val source: SimpleSource<Lifecycle.Event> = SimpleSource(initialValue = null, emitOnConnect = true)
20+
) : Lifecycle, Source<Lifecycle.Event> by source {
1821
fun begin() {
1922
source(BEGIN)
2023
}

0 commit comments

Comments
 (0)