@@ -17,25 +17,25 @@ import java.lang.ref.WeakReference
17
17
import java.util.concurrent.locks.ReentrantLock
18
18
19
19
abstract class RCKViewModel <S : State >(application : Application ): AndroidViewModel(application) {
20
- val token: Token =
21
- Token ()
20
+ val token: Token = Token ()
22
21
23
22
private val rx_action: BehaviorRelay <Action > = BehaviorRelay .createDefault(
24
23
VoidAction
25
24
)
26
25
private val store = Store <S >()
27
26
private val disposables = CompositeDisposable ()
27
+ private var actionQueue: Queue <Action > = Queue ()
28
28
private val writeLock = ReentrantLock ()
29
29
private val readLock = ReentrantLock ()
30
30
private var subscribers: MutableList <WeakReference <StateSubscriber >> = mutableListOf ()
31
31
32
32
init {
33
- setupRxStream()
33
+ this . setupRxStream()
34
34
this .setupStore()
35
35
}
36
36
37
37
override fun onCleared () {
38
- dispose()
38
+ this . dispose()
39
39
super .onCleared()
40
40
}
41
41
@@ -44,6 +44,7 @@ abstract class RCKViewModel<S: State>(application: Application): AndroidViewMode
44
44
*/
45
45
fun dispose () {
46
46
RCK .unregisterViewModel(token)
47
+ actionQueue.clear()
47
48
subscribers = mutableListOf ()
48
49
disposables.dispose()
49
50
store.deinitialize()
@@ -55,12 +56,21 @@ abstract class RCKViewModel<S: State>(application: Application): AndroidViewMode
55
56
.filter { action ->
56
57
action !is VoidAction
57
58
}
59
+ .filter { action ->
60
+ store.actionFlow(action) !is VoidAction
61
+ }
58
62
.flatMap { action ->
59
63
store.dispatch(action).toObservable()
60
64
}
61
65
.observeOn(AndroidSchedulers .mainThread())
62
66
.doAfterNext {
63
67
store.doAfterEffects()
68
+ if (actionQueue.isNotEmpty) {
69
+ val nextAction = actionQueue.dequeue()
70
+ nextAction?.let {
71
+ rx_action.accept(it)
72
+ }
73
+ }
64
74
}
65
75
.subscribe { newState ->
66
76
if (newState.error != null ) {
@@ -70,6 +80,8 @@ abstract class RCKViewModel<S: State>(application: Application): AndroidViewMode
70
80
} else {
71
81
dispatchStateToSubscribers(newState)
72
82
}
83
+
84
+
73
85
}
74
86
75
87
disposables.add(disposable)
@@ -101,6 +113,17 @@ abstract class RCKViewModel<S: State>(application: Application): AndroidViewMode
101
113
rx_action.accept(action)
102
114
}
103
115
116
+ /* *
117
+ * dispatch action on the next run loop to the store.
118
+ */
119
+ fun nextDispatch (action : Action ) {
120
+ if (actionQueue.isEmpty) {
121
+ rx_action.accept(action)
122
+ } else {
123
+ actionQueue.enqueue(action)
124
+ }
125
+ }
126
+
104
127
/* *
105
128
* Called when receive the new state from store
106
129
*/
@@ -129,12 +152,14 @@ abstract class RCKViewModel<S: State>(application: Application): AndroidViewMode
129
152
* Set state and dispatch the mutated state to subscribers
130
153
*/
131
154
@Suppress(" UNCHECKED_CAST" )
132
- fun setState (block : RCKViewModel < S > .(S ) -> S ): S {
155
+ fun setState (block : S .(S ) -> S ): S {
133
156
writeLock.lock()
134
157
try {
135
- val newState = block(this .store.state.copyState() as S )
158
+ val state = this .store.state.copyState() as S
159
+ val newState = state.block(state)
160
+ this .store.state = newState
136
161
runOnUiThread {
137
- this .on (newState)
162
+ dispatchStateToSubscribers (newState)
138
163
}
139
164
return newState
140
165
} finally {
@@ -146,10 +171,11 @@ abstract class RCKViewModel<S: State>(application: Application): AndroidViewMode
146
171
* Read state value
147
172
*/
148
173
@Suppress(" UNCHECKED_CAST" )
149
- fun <R > withState (block : RCKViewModel < S > .(S ) -> R ): R {
174
+ fun <R > withState (block : S .(S ) -> R ): R {
150
175
readLock.lock()
151
176
try {
152
- return block(this .store.state.copyState() as S )
177
+ val state = this .store.state.copyState() as S
178
+ return state.block(state)
153
179
} finally {
154
180
readLock.unlock()
155
181
}
0 commit comments