Skip to content

Commit 2653d21

Browse files
author
Alex
committed
add ConfirmationEvent
1 parent e52981b commit 2653d21

File tree

6 files changed

+122
-5
lines changed

6 files changed

+122
-5
lines changed

reactiveviewmodel/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ afterEvaluate {
4444
release(MavenPublication) {
4545
from components.release
4646
groupId = 'com.alexdeww.reactiveviewmodel'
47-
version = '2.3.8'
47+
version = '2.3.9'
4848
}
4949
}
5050
}

reactiveviewmodel/src/main/java/com/alexdeww/reactiveviewmodel/core/ReactiveViewModel.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.alexdeww.reactiveviewmodel.core
33
import androidx.lifecycle.ViewModel
44
import com.alexdeww.reactiveviewmodel.core.common.RvmComponent
55
import com.alexdeww.reactiveviewmodel.core.property.Action
6+
import com.alexdeww.reactiveviewmodel.core.property.ConfirmationEvent
67
import com.alexdeww.reactiveviewmodel.core.property.Event
78
import com.alexdeww.reactiveviewmodel.core.property.State
89
import io.reactivex.rxjava3.disposables.CompositeDisposable
@@ -36,6 +37,12 @@ abstract class ReactiveViewModel : ViewModel(), RvmComponent {
3637
protected fun eventNone(debounceInterval: Long? = null): Event<Unit> =
3738
Event(debounceInterval)
3839

40+
protected fun <T : Any> confirmationEvent(debounceInterval: Long? = null): ConfirmationEvent<T> =
41+
ConfirmationEvent(debounceInterval)
42+
43+
protected fun confirmationEventNone(debounceInterval: Long? = null): ConfirmationEvent<Unit> =
44+
ConfirmationEvent(debounceInterval)
45+
3946
protected fun <T : Any> action(debounceInterval: Long? = null): Action<T> =
4047
Action(debounceInterval)
4148

reactiveviewmodel/src/main/java/com/alexdeww/reactiveviewmodel/core/RvmExtensions.kt

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import androidx.lifecycle.LifecycleOwner
55
import androidx.lifecycle.LiveData
66
import androidx.lifecycle.Observer
77
import com.alexdeww.reactiveviewmodel.core.property.Action
8+
import com.alexdeww.reactiveviewmodel.core.property.ConfirmationEvent
89
import com.alexdeww.reactiveviewmodel.core.property.Event
910
import com.alexdeww.reactiveviewmodel.core.property.State
1011
import io.reactivex.rxjava3.core.*
@@ -19,11 +20,20 @@ fun <T> LiveData<T>.observe(owner: LifecycleOwner, action: OnLiveDataAction<T>):
1920
return observer
2021
}
2122

22-
fun <T : Any> Event<T>.observe(owner: LifecycleOwner, action: OnLiveDataAction<T>): Observer<T> =
23-
liveData.observe(owner = owner, action = action)
23+
fun <T : Any> Event<T>.observe(
24+
owner: LifecycleOwner,
25+
action: OnLiveDataAction<T>
26+
): Observer<T> = liveData.observe(owner = owner, action = action)
2427

25-
fun <T : Any> State<T>.observe(owner: LifecycleOwner, action: OnLiveDataAction<T>): Observer<T> =
26-
liveData.observe(owner = owner, action = action)
28+
fun <T : Any> ConfirmationEvent<T>.observe(
29+
owner: LifecycleOwner,
30+
action: OnLiveDataAction<T>
31+
): Observer<T> = liveData.observe(owner = owner, action = action)
32+
33+
fun <T : Any> State<T>.observe(
34+
owner: LifecycleOwner,
35+
action: OnLiveDataAction<T>
36+
): Observer<T> = liveData.observe(owner = owner, action = action)
2737

2838
fun Action<Unit>.call() = call(Unit)
2939

reactiveviewmodel/src/main/java/com/alexdeww/reactiveviewmodel/core/RvmViewComponent.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import android.widget.RatingBar
66
import androidx.lifecycle.LifecycleOwner
77
import androidx.lifecycle.LiveData
88
import androidx.lifecycle.Observer
9+
import com.alexdeww.reactiveviewmodel.core.property.ConfirmationEvent
910
import com.alexdeww.reactiveviewmodel.core.property.Event
1011
import com.alexdeww.reactiveviewmodel.core.property.State
1112
import com.alexdeww.reactiveviewmodel.widget.*
@@ -31,6 +32,9 @@ interface RvmViewComponent {
3132
fun <T : Any> Event<T>.observe(action: OnLiveDataAction<T>): Observer<T> =
3233
observe(componentLifecycleOwner, action)
3334

35+
fun <T : Any> ConfirmationEvent<T>.observe(action: OnLiveDataAction<T>): Observer<T> =
36+
observe(componentLifecycleOwner, action)
37+
3438
fun <T : Any> DisplayableControl<T>.observe(
3539
action: DisplayableAction<T>
3640
): Observer<DisplayableControl.Action<T>> = this@observe.action.observe {

reactiveviewmodel/src/main/java/com/alexdeww/reactiveviewmodel/core/common/RvmComponent.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.alexdeww.reactiveviewmodel.core.common
22

33
import com.alexdeww.reactiveviewmodel.core.property.Action
4+
import com.alexdeww.reactiveviewmodel.core.property.ConfirmationEvent
45
import com.alexdeww.reactiveviewmodel.core.property.Event
56
import com.alexdeww.reactiveviewmodel.core.property.State
67
import io.reactivex.rxjava3.core.Observable
@@ -30,4 +31,12 @@ interface RvmComponent {
3031

3132
val <T : Any> Event<T>.observable: Observable<T> get() = this.observable
3233

34+
fun <T : Any> ConfirmationEvent<T>.call(value: T) = this.consumer.accept(value)
35+
36+
fun ConfirmationEvent<Unit>.call() = this.consumer.accept(Unit)
37+
38+
val <T : Any> ConfirmationEvent<T>.consumer: Consumer<T> get() = this.consumer
39+
40+
val <T : Any> ConfirmationEvent<T>.observable: Observable<T> get() = this.observable
41+
3342
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package com.alexdeww.reactiveviewmodel.core.property
2+
3+
import androidx.annotation.MainThread
4+
import androidx.collection.ArraySet
5+
import androidx.lifecycle.LifecycleOwner
6+
import androidx.lifecycle.LiveData
7+
import androidx.lifecycle.MediatorLiveData
8+
import androidx.lifecycle.Observer
9+
import com.alexdeww.reactiveviewmodel.core.property.ConfirmationEvent.ObserverWrapper
10+
import io.reactivex.rxjava3.core.Flowable
11+
import io.reactivex.rxjava3.core.Observable
12+
import io.reactivex.rxjava3.functions.Consumer
13+
14+
class ConfirmationEvent<T : Any> internal constructor(debounceInterval: Long? = null) {
15+
16+
private sealed class EventType {
17+
data class Pending(val data: Any) : EventType()
18+
object Confirmed : EventType()
19+
}
20+
21+
private val eventState = State<EventType>(EventType.Confirmed, debounceInterval)
22+
23+
internal val consumer: Consumer<T> = Consumer {
24+
eventState.consumer.accept(EventType.Pending(it))
25+
}
26+
27+
@Suppress("UNCHECKED_CAST")
28+
internal val observable: Observable<T> = eventState.observable
29+
.ofType(EventType.Pending::class.java)
30+
.map { it.data as T }
31+
32+
val liveData: LiveData<T> by lazy { ConfirmationEventLiveData() }
33+
val viewFlowable: Flowable<T> by lazy { observable.toViewFlowable() }
34+
val isConfirmed: Boolean get() = eventState.value === EventType.Confirmed
35+
36+
fun confirm() {
37+
eventState.consumer.accept(EventType.Confirmed)
38+
}
39+
40+
private inner class ConfirmationEventLiveData : MediatorLiveData<T>() {
41+
42+
private val observers = ArraySet<ConfirmationEvent.ObserverWrapper<T>>()
43+
44+
@MainThread
45+
override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
46+
val wrapper = ObserverWrapper(observer)
47+
observers.add(wrapper)
48+
super.observe(owner, wrapper)
49+
}
50+
51+
@MainThread
52+
override fun removeObserver(observer: Observer<in T>) {
53+
if (observers.remove(observer as Observer<*>)) {
54+
super.removeObserver(observer)
55+
return
56+
}
57+
58+
val iterator = observers.iterator()
59+
while (iterator.hasNext()) {
60+
val wrapper = iterator.next()
61+
if (wrapper.observer == observer) {
62+
iterator.remove()
63+
super.removeObserver(observer)
64+
break
65+
}
66+
}
67+
}
68+
69+
@Suppress("UNCHECKED_CAST")
70+
override fun onActive() {
71+
super.onActive()
72+
addSource(eventState.liveData) { value = (it as? EventType.Pending)?.data as T }
73+
}
74+
75+
override fun onInactive() {
76+
removeSource(eventState.liveData)
77+
super.onInactive()
78+
}
79+
}
80+
81+
private class ObserverWrapper<T>(val observer: Observer<in T>) : Observer<T> {
82+
override fun onChanged(t: T?) {
83+
if (t != null) observer.onChanged(t)
84+
}
85+
}
86+
87+
}

0 commit comments

Comments
 (0)