@@ -22,6 +22,7 @@ import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion.AP
22
22
import androidx.lifecycle.viewModelScope
23
23
import androidx.lifecycle.viewmodel.initializer
24
24
import androidx.lifecycle.viewmodel.viewModelFactory
25
+ import com.google.firebase.dataconnect.minimaldemo.connector.DeleteItemByKeyMutation
25
26
import com.google.firebase.dataconnect.minimaldemo.connector.GetItemByKeyQuery
26
27
import com.google.firebase.dataconnect.minimaldemo.connector.InsertItemMutation
27
28
import com.google.firebase.dataconnect.minimaldemo.connector.Zwda6x9zyyKey
@@ -33,6 +34,7 @@ import java.util.Objects
33
34
import kotlinx.coroutines.CoroutineStart
34
35
import kotlinx.coroutines.Deferred
35
36
import kotlinx.coroutines.ExperimentalCoroutinesApi
37
+ import kotlinx.coroutines.Job
36
38
import kotlinx.coroutines.async
37
39
import kotlinx.coroutines.flow.MutableStateFlow
38
40
import kotlinx.coroutines.flow.StateFlow
@@ -46,6 +48,7 @@ class MainActivityViewModel(private val app: MyApplication) : ViewModel() {
46
48
State (
47
49
insertItem = State .OperationState .New ,
48
50
getItem = State .OperationState .New ,
51
+ deleteItem = State .OperationState .New ,
49
52
lastInsertedKey = null ,
50
53
nextSequenceNumber = 19999000 ,
51
54
)
@@ -180,41 +183,84 @@ class MainActivityViewModel(private val app: MyApplication) : ViewModel() {
180
183
return true
181
184
}
182
185
186
+ fun deleteItem () {
187
+ while (true ) {
188
+ if (tryDeleteItem()) {
189
+ break
190
+ }
191
+ }
192
+ }
193
+
194
+ private fun tryDeleteItem (): Boolean {
195
+ val oldState = _state .value
196
+
197
+ // If there is no previous successful "insert" operation, then we don't know any ID's to delete,
198
+ // so just do nothing.
199
+ val key: Zwda6x9zyyKey = oldState.lastInsertedKey ? : return true
200
+
201
+ // If there is already a "delete" in progress, then just return and let the in-progress
202
+ // operation finish.
203
+ when (oldState.deleteItem) {
204
+ is State .OperationState .InProgress -> return true
205
+ is State .OperationState .New ,
206
+ is State .OperationState .Completed -> Unit
207
+ }
208
+
209
+ // Create a new coroutine to perform the "delete" operation, but don't start it yet by
210
+ // specifying start=CoroutineStart.LAZY because we won't start it until the state is
211
+ // successfully set.
212
+ val newDeleteJob: Deferred <Unit > =
213
+ viewModelScope.async(start = CoroutineStart .LAZY ) {
214
+ app.getConnector().deleteItemByKey.execute(key)
215
+ }
216
+
217
+ // Update the state and start the coroutine if it is successfully set.
218
+ val deleteItemOperationInProgressState =
219
+ State .OperationState .InProgress (oldState.nextSequenceNumber, key, newDeleteJob)
220
+ val newState = oldState.withDeleteInProgress(deleteItemOperationInProgressState)
221
+ if (! _state .compareAndSet(oldState, newState)) {
222
+ return false
223
+ }
224
+
225
+ // Actually start the coroutine now that the state has been set.
226
+ Log .i(TAG , " Deleting item with key: $key " )
227
+ newState.startDelete(deleteItemOperationInProgressState)
228
+ return true
229
+ }
230
+
183
231
@OptIn(ExperimentalCoroutinesApi ::class )
184
- private fun State.startGet (
185
- getItemOperationInProgressState :
186
- State .OperationState .InProgress <Zwda6x9zyyKey , GetItemByKeyQuery .Data .Item ?>
232
+ private fun State.startDelete (
233
+ deleteItemOperationInProgressState : State .OperationState .InProgress <Zwda6x9zyyKey , Unit >
187
234
) {
188
- require(getItemOperationInProgressState == = getItem )
189
- val job: Deferred < GetItemByKeyQuery . Data . Item ?> = getItemOperationInProgressState .job
190
- val key: Zwda6x9zyyKey = getItemOperationInProgressState .variables
235
+ require(deleteItemOperationInProgressState == = deleteItem )
236
+ val job: Job = deleteItemOperationInProgressState .job
237
+ val key: Zwda6x9zyyKey = deleteItemOperationInProgressState .variables
191
238
192
239
job.start()
193
240
194
241
job.invokeOnCompletion { exception ->
195
242
val result =
196
243
if (exception != = null ) {
197
- Log .w(TAG , " WARNING: Getting item with key $key FAILED: $exception " , exception)
244
+ Log .w(TAG , " WARNING: Deleting item with key $key FAILED: $exception " , exception)
198
245
Result .failure(exception)
199
246
} else {
200
- val item = job.getCompleted()
201
- Log .i(TAG , " Got item with key $key : $item " )
202
- Result .success(item)
247
+ Log .i(TAG , " Deleted item with key $key " )
248
+ Result .success(Unit )
203
249
}
204
250
205
251
while (true ) {
206
252
val oldState = _state .value
207
- if (oldState.getItem != = getItemOperationInProgressState ) {
253
+ if (oldState.deleteItem != = deleteItemOperationInProgressState ) {
208
254
break
209
255
}
210
256
211
- val getItemOperationCompletedState =
257
+ val deleteItemOperationCompletedState =
212
258
State .OperationState .Completed (
213
259
oldState.nextSequenceNumber,
214
- getItemOperationInProgressState .variables,
260
+ deleteItemOperationInProgressState .variables,
215
261
result,
216
262
)
217
- val newState = oldState.withGetCompleted(getItemOperationCompletedState )
263
+ val newState = oldState.withDeleteCompleted(deleteItemOperationCompletedState )
218
264
if (_state .compareAndSet(oldState, newState)) {
219
265
break
220
266
}
@@ -226,6 +272,7 @@ class MainActivityViewModel(private val app: MyApplication) : ViewModel() {
226
272
class State (
227
273
val insertItem : OperationState <InsertItemMutation .Variables , Zwda6x9zyyKey >,
228
274
val getItem : OperationState <Zwda6x9zyyKey , GetItemByKeyQuery .Data .Item ?>,
275
+ val deleteItem : OperationState <Zwda6x9zyyKey , Unit >,
229
276
val lastInsertedKey : Zwda6x9zyyKey ? ,
230
277
val nextSequenceNumber : Long ,
231
278
) {
@@ -236,6 +283,7 @@ class MainActivityViewModel(private val app: MyApplication) : ViewModel() {
236
283
State (
237
284
insertItem = insertItem,
238
285
getItem = getItem,
286
+ deleteItem = deleteItem,
239
287
lastInsertedKey = lastInsertedKey,
240
288
nextSequenceNumber = nextSequenceNumber + 1 ,
241
289
)
@@ -246,6 +294,7 @@ class MainActivityViewModel(private val app: MyApplication) : ViewModel() {
246
294
State (
247
295
insertItem = insertItem,
248
296
getItem = getItem,
297
+ deleteItem = deleteItem,
249
298
lastInsertedKey = insertItem.result.getOrNull() ? : lastInsertedKey,
250
299
nextSequenceNumber = nextSequenceNumber + 1 ,
251
300
)
@@ -256,6 +305,7 @@ class MainActivityViewModel(private val app: MyApplication) : ViewModel() {
256
305
State (
257
306
insertItem = insertItem,
258
307
getItem = getItem,
308
+ deleteItem = deleteItem,
259
309
lastInsertedKey = lastInsertedKey,
260
310
nextSequenceNumber = nextSequenceNumber + 1 ,
261
311
)
@@ -266,6 +316,29 @@ class MainActivityViewModel(private val app: MyApplication) : ViewModel() {
266
316
State (
267
317
insertItem = insertItem,
268
318
getItem = getItem,
319
+ deleteItem = deleteItem,
320
+ lastInsertedKey = lastInsertedKey,
321
+ nextSequenceNumber = nextSequenceNumber + 1 ,
322
+ )
323
+
324
+ fun withDeleteInProgress (
325
+ deleteItem : OperationState .InProgress <Zwda6x9zyyKey , Unit >
326
+ ): State =
327
+ State (
328
+ insertItem = insertItem,
329
+ getItem = getItem,
330
+ deleteItem = deleteItem,
331
+ lastInsertedKey = lastInsertedKey,
332
+ nextSequenceNumber = nextSequenceNumber + 1 ,
333
+ )
334
+
335
+ fun withDeleteCompleted (
336
+ deleteItem : OperationState .Completed <Zwda6x9zyyKey , Unit >
337
+ ): State =
338
+ State (
339
+ insertItem = insertItem,
340
+ getItem = getItem,
341
+ deleteItem = deleteItem,
269
342
lastInsertedKey = lastInsertedKey,
270
343
nextSequenceNumber = nextSequenceNumber + 1 ,
271
344
)
@@ -276,13 +349,15 @@ class MainActivityViewModel(private val app: MyApplication) : ViewModel() {
276
349
other is State &&
277
350
insertItem == other.insertItem &&
278
351
getItem == other.getItem &&
352
+ deleteItem == other.deleteItem &&
279
353
lastInsertedKey == other.lastInsertedKey &&
280
354
nextSequenceNumber == other.nextSequenceNumber
281
355
282
356
override fun toString () =
283
357
" State(" +
284
358
" insertItem=$insertItem , " +
285
359
" getItem=$getItem , " +
360
+ " deleteItem=$deleteItem , " +
286
361
" lastInsertedKey=$lastInsertedKey , " +
287
362
" sequenceNumber=$nextSequenceNumber )"
288
363
0 commit comments