Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not consumed events when Lifecycle ends #157

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions binding-order/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
21 changes: 21 additions & 0 deletions binding-order/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
plugins {
id 'java-library'
id 'org.jetbrains.kotlin.jvm'
}

java {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
}

dependencies {
implementation project(":mvicore")

implementation deps("org.jetbrains.kotlin:kotlin-stdlib-jdk7")

implementation deps('io.reactivex.rxjava2:rxjava')
implementation deps('io.reactivex.rxjava2:rxandroid')

testImplementation deps('junit:junit')
testImplementation deps('org.mockito.kotlin:mockito-kotlin')
}
38 changes: 38 additions & 0 deletions binding-order/src/main/java/com/bumble/order/ComponentBinder.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.bumble.order

import com.badoo.binder.Binder
import com.badoo.binder.lifecycle.ManualLifecycle
import com.badoo.binder.using
import com.bumble.order.component.Analytics
import com.bumble.order.component.Feature
import com.bumble.order.component.NewsConsumer
import com.bumble.order.component.StateToViewModel
import com.bumble.order.component.View
import com.bumble.order.component.ViewEventToAnalyticsEvent
import com.bumble.order.component.ViewEventToWish

class ComponentBinder(
private val view: View = View(),
private val feature: Feature = Feature(),
private val analytics: Analytics = Analytics(),
lifecycle: ManualLifecycle = ManualLifecycle(),
private val newsConsumer: NewsConsumer = NewsConsumer(lifecycle)
) {
private val binder = Binder(lifecycle)

//Works like a charm
fun bindAnalyticsFirst() {
binder.bind(view to analytics using ViewEventToAnalyticsEvent)
binder.bind(view to feature using ViewEventToWish)
binder.bind(feature to view using StateToViewModel)
binder.bind(feature.news to newsConsumer)
}

//Analytics class does not get the last event from the view class
fun bindFeatureFirst() {
binder.bind(view to feature using ViewEventToWish)
binder.bind(view to analytics using ViewEventToAnalyticsEvent)
binder.bind(feature to view using StateToViewModel)
binder.bind(feature.news to newsConsumer)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.bumble.order.component

import io.reactivex.functions.Consumer

class Analytics : Consumer<Analytics.Event> {

sealed class Event {
object Point : Event()
}

override fun accept(event: Event) {
when (event) {
is Event.Point -> println("Analytics: ${event::class.java.simpleName}")
}
}
}
43 changes: 43 additions & 0 deletions binding-order/src/main/java/com/bumble/order/component/Feature.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.bumble.order.component

import com.badoo.mvicore.element.Reducer
import com.badoo.mvicore.feature.ReducerFeature

class Feature : ReducerFeature<Feature.Wish, Feature.State, Feature.News>(
initialState = State(),
reducer = ReducerImpl(),
newsPublisher = NewsPublisher()
) {

data class State(val score: Int = 0)

sealed class Wish {
object Point : Wish()
}

sealed class News {
object MaxScoreReached : News()
}

class ReducerImpl : Reducer<State, Wish> {
override fun invoke(state: State, effect: Wish): State {
return when (effect) {
Wish.Point -> state.copy(score = state.score.inc())
}
}
}

class NewsPublisher : SimpleNewsPublisher<Wish, State, News>() {
override fun invoke(wish: Wish, state: State): News? {
return if (state.score == SCORE_LIMIT) {
News.MaxScoreReached
} else {
null
}
}
}

private companion object {
const val SCORE_LIMIT = 5
}
}
23 changes: 23 additions & 0 deletions binding-order/src/main/java/com/bumble/order/component/Mappers.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.bumble.order.component

object ViewEventToWish : (View.Event) -> Feature.Wish {
override fun invoke(event: View.Event): Feature.Wish {
return when (event) {
View.Event.Point -> Feature.Wish.Point
}
}
}

object ViewEventToAnalyticsEvent : (View.Event) -> Analytics.Event {
override fun invoke(event: View.Event): Analytics.Event {
return when (event) {
View.Event.Point -> Analytics.Event.Point
}
}
}

object StateToViewModel : (Feature.State) -> View.ViewModel {
override fun invoke(state: Feature.State): View.ViewModel {
return View.ViewModel(state.score)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.bumble.order.component

import com.badoo.binder.lifecycle.ManualLifecycle
import io.reactivex.functions.Consumer

class NewsConsumer(private val lifecycle: ManualLifecycle) : Consumer<Feature.News> {
override fun accept(news: Feature.News) {
when (news) {
Feature.News.MaxScoreReached -> {
lifecycle.end()
println("--FINISH--")
}
}
}
}
24 changes: 24 additions & 0 deletions binding-order/src/main/java/com/bumble/order/component/View.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.bumble.order.component

import io.reactivex.ObservableSource
import io.reactivex.functions.Consumer
import io.reactivex.subjects.PublishSubject

class View(
private val events: PublishSubject<Event> = PublishSubject.create<Event>()
) : Consumer<View.ViewModel>, ObservableSource<View.Event> by events {

data class ViewModel(val score: Int = 0)

sealed class Event {
object Point : Event()
}

fun score() {
events.onNext(Event.Point)
}

override fun accept(viewModel: ViewModel) {
println("View ${viewModel.score}")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.bumble.order

import com.badoo.binder.lifecycle.ManualLifecycle
import com.bumble.order.component.Analytics
import com.bumble.order.component.View
import org.junit.Ignore
import org.junit.Test
import org.mockito.kotlin.any
import org.mockito.kotlin.spy
import org.mockito.kotlin.times
import org.mockito.kotlin.verify

class BindingOrderDisposeTest {

@Test
@Ignore
fun `missing events on dispose`() {
val lifecycle = ManualLifecycle()
val view = spy(View())
val analytics = spy(Analytics())
val componentBinder =
ComponentBinder(view = view, analytics = analytics, lifecycle = lifecycle)
componentBinder.bindFeatureFirst()

lifecycle.begin()
repeat(SCORE_LIMIT) { view.score() }

verify(view, times(SCORE_LIMIT + 1)).accept(any()) //+1 initial feature state
verify(analytics, times(SCORE_LIMIT)).accept(any())
}

private companion object {
const val SCORE_LIMIT = 5
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mock-maker-inline
1 change: 1 addition & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ include ':mvicore-demo:mvicore-demo-feature1'
include ':mvicore-demo:mvicore-demo-feature2'
include ':mvicore-demo:mvicore-demo-app'

include ':binding-order'