/**
* This allows us to group all the_viewEvents from
* one view in a single Flow.
*/
interface ViewEventFlow {
funxviewEvents():xFlow
}x
class MainActivity_: ViewEventFlow {x_
override_fun_viewEvents(): Flow_{
val flows = listOf(
heartButton.clicks().map { MainViewEvent.LoveItClick },
thumbButton.clicks().map { MainViewEvent.ThumbsUpClick }
)x
return flows.asFlow().flattenMerge(flows.size)_
}_
}__
View
❤ ❤
ModelState
store
Model
val ❤:Int
val :Int
data class UpvoteModel(val hearts:Int, val thumbs:Int)
(Don’t mind me. My
turn is coming up
soon.)
Slide 52
Slide 52 text
ModelState
store
Intent
View
Model
data class UpvoteModel(val hearts:Int, val thumbs:Int)
newState = oldState.copy(thumbs = thumbs + 1) // 0, 1
newState = newState.copy(hearts = hearts + 1) // 1, 1
newState = newState.copy(hearts = hearts + 1) // 2, 1
val ❤ :Int
val :Int
❓
Slide 53
Slide 53 text
ModelState
store
Intent
View
Model
data class UpvoteModel(val hearts:Int, val thumbs:Int)
interface Intent {x
fun reduce(oldState: T): T
}x
val ❤ :Int
val :Int
Slide 54
Slide 54 text
ModelState
store
Intent
View
Model
data class UpvoteModel(val hearts:Int, val thumbs:Int)
interface Intent {x
fun reduce(oldState: T): T
}x
class AddHeart():Intent {y
override fun reduce(oldState: UpvoteModel)_=
oldState.copy(hearts =_oldState.hearts_+ 1)
}y
val ❤ :Int
val :Int
Slide 55
Slide 55 text
ModelState
store
Intent
View
Model
data class UpvoteModel(val hearts:Int, val thumbs:Int)
fun_toIntent(viewEvent: MainViewEvent):Intent_{
return when (viewEvent) {z
MainViewEvent.LoveItClick ->_AddHeart()
MainViewEvent.ThumbsUpClick ->_AddThumb()
}z
}z2
val ❤ :Int
val :Int
ModelStore
RxModelStore
UpvoteModelStore
FlowModelStore
Intent
interface_ModelStore_{y
suspend_fun process(intent: Intent)
fun modelState(): Flow
}yy
override suspend fun_process(viewEvent: MainViewEvent)_{
UpvoteModelStore.process(toIntent(viewEvent))
}x
(Don’t mind me. My
turn is coming up soon
too.)
Model
val ❤ :Int
val :Int
ModelState
store
+ +
+
Slide 61
Slide 61 text
Intent
interface_ModelStore_{y
suspend_fun process(intent: Intent)
fun modelState(): Flow
}yy
Model
val ❤ :Int
val :Int
ModelState
store
+ +
+
ModelStore
RxModelStore
UpvoteModelStore
FlowModelStore
(Don’t mind me. My
turn is coming up soon
too.)
Slide 62
Slide 62 text
x
+❤ +❤
+
Intent
ModelState
store
Hi again!
interface_ModelStore_{y
suspend_fun process(intent: Intent)
fun modelState(): Flow
}yy
Slide 63
Slide 63 text
x
val intents = Channel>()
+❤ +❤
+
Intent
ModelState
store
suspend fun process(intent: Intent) {
intents.send(intent)
}
~
Slide 64
Slide 64 text
x
val intents = Channel>()
+❤ +❤
+
Intent
ModelState
store
suspend fun process(intent: Intent) {
intents.send(intent)
}
~
val store = ConflatedBroadcastChannel(startingState)
override fun modelState(): Flow {
return store.asFlow()
}
Slide 65
Slide 65 text
val intents = Channel>()
+❤ +❤
+
Intent
ModelState
store
❓❓❓
val store = ConflatedBroadcastChannel(startingState)
Slide 66
Slide 66 text
+❤ +❤
+
Intent
0❤, 0
0❤, 0
1❤, 1 2❤, 1
ModelState
store
store.offer(intents.receive().reduce(store.value))
val store = ConflatedBroadcastChannel(startingState)
val intents = Channel>()
0❤, 1
Slide 67
Slide 67 text
open class FlowModelStore(startingState: S) : ModelStore {
private val scope = MainScope()
private val intents = Channel>()
private val store = ConflatedBroadcastChannel(startingState)
init {
// Reduce from MainScope()
scope.launch {
while (isActive) store.offer(intents.receive().reduce(store.value))
}
}
// Could be called from any coroutine scope/context.
override suspend fun process(intent: Intent) {
intents.send(intent)
}
override fun modelState(): Flow {
return store.asFlow()
}
fun close() {
intents.close()
store.close()
scope.cancel()
}
}
ModelStore
RxModelStore
UpvoteModelStore
FlowModelStore
Slide 68
Slide 68 text
interface_ModelStore_{
suspend fun process(intent: Intent)
fun modelState(): Flow
}x
object UpvoteModelStore :_
FlowModelStore(UpvoteModel(0, 0))
open class FlowModelStore(startingState: S) : ModelStore {
// ...
}
ModelStore
FlowModelStore
UpvoteModelStore
Intent
View
Model
val ❤ :Int
val :Int
ModelState
store
object UpvoteModelStore
Slide 71
Slide 71 text
Intent
View
Model
val ❤ :Int
val :Int
ModelState
store
interface_ModelStore_{
fun process(intent: Intent)
fun modelState(): Flow
}x
fun modelState(): Flow
object UpvoteModelStore
Slide 72
Slide 72 text
View
Model
fun Flow.forCounterTextView() =
onEach { model ->
counterTextView.text =
}
// Input(s)
UpvoteModelStore
.modelState()
.forCounterTextView()
.launchIn(scope)
0❤, 1
0❤, 0 1❤, 1 2❤, 1
Slide 73
Slide 73 text
Live demo?
Slide 74
Slide 74 text
https://github.com/kanawish/upvote
Slide 75
Slide 75 text
Photo source info here
Thank you!
https://github.com/kanawish/upvote