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

Shopping Cart - Actor with StateFlow #29

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -2,7 +2,7 @@ package com.handstandsam.shoppingapp.di

import android.content.Context
import androidx.room.Room
import com.handstandsam.shoppingapp.cart.InMemoryShoppingCartDao
import com.handstandsam.shoppingapp.cart.InMemoryShoppingCartDaoActorWithFlow
import com.handstandsam.shoppingapp.cart.RoomItemInCartDatabase
import com.handstandsam.shoppingapp.cart.RoomShoppingCartDao
import com.handstandsam.shoppingapp.cart.ShoppingCart
@@ -29,7 +29,7 @@ class SessionGraphImpl(

private val shoppingCartDao: ShoppingCartDao = when (dbType) {
DatabaseType.IN_MEMORY -> {
InMemoryShoppingCartDao()
InMemoryShoppingCartDaoActorWithFlow()
}
DatabaseType.ROOM -> {
RoomShoppingCartDao(
@@ -36,9 +36,4 @@ class InMemoryShoppingCartDao : ShoppingCartDao {
override val allItems: Flow<List<ItemWithQuantity>>
get() = channel.asFlow()

private fun MutableMap<String, ItemWithQuantity>.asSortedList(): List<ItemWithQuantity> {
return values.toList()
.sortedBy { it.item.label }
}

}
@@ -0,0 +1,81 @@
package com.handstandsam.shoppingapp.cart

import com.handstandsam.shoppingapp.models.ItemWithQuantity
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.actor
import kotlinx.coroutines.flow.MutableStateFlow

/**
* In memory implementation of our [ShoppingCartDao]
*/
class InMemoryShoppingCartDaoActorWithFlow : ShoppingCartDao {

override val allItems = MutableStateFlow<List<ItemWithQuantity>>(listOf())

sealed class Intention {
class FindByLabel(
val label: String,
val deferred: CompletableDeferred<ItemWithQuantity?>
) : Intention()

class Upsert(val itemWithQuantity: ItemWithQuantity) : Intention()

class Remove(val itemWithQuantity: ItemWithQuantity) : Intention()

object Empty : Intention()
}

private val scope = CoroutineScope(Dispatchers.Default)

private val actor = scope.actor<Intention> {

val itemsInCart: MutableMap<String, ItemWithQuantity> = mutableMapOf()

for (intention in channel) {
when (intention) {
is Intention.FindByLabel -> {
intention.deferred.complete(itemsInCart[intention.label])
}
is Intention.Upsert -> {
itemsInCart[intention.itemWithQuantity.item.label] = intention.itemWithQuantity
}
is Intention.Remove -> itemsInCart.remove(intention.itemWithQuantity.item.label)
is Intention.Empty -> itemsInCart.clear()
}

val sortedItems = itemsInCart.asSortedList()

if (allItems.value != sortedItems) {
allItems.value = sortedItems
} else {
// No change detected, don't emit
}
}
}

override suspend fun findByLabel(label: String): ItemWithQuantity? {
val deferred = CompletableDeferred<ItemWithQuantity?>()
actor.send(
Intention.FindByLabel(
label = label,
deferred = deferred
)
)
return deferred.await()
}

override suspend fun upsert(itemWithQuantity: ItemWithQuantity) {
actor.send(Intention.Upsert(itemWithQuantity))
}

override suspend fun remove(itemWithQuantity: ItemWithQuantity) {
actor.send(Intention.Remove(itemWithQuantity))
}

override suspend fun empty() {
actor.send(Intention.Empty)
}

}
@@ -0,0 +1,9 @@
package com.handstandsam.shoppingapp.cart

import com.handstandsam.shoppingapp.models.ItemWithQuantity


internal fun MutableMap<String, ItemWithQuantity>.asSortedList(): List<ItemWithQuantity> {
return values.toList()
.sortedBy { it.item.label }
}