Last active
June 23, 2020 20:16
-
-
Save thegarlynch/2d89a736a7e0e6cb014a9b0b332f20e1 to your computer and use it in GitHub Desktop.
Implementation of cart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import com.myapplication.domain.model.checkout.CartItem | |
| import com.myapplication.helper.rx.ThreadConfinedBehaviorSubject | |
| import io.reactivex.Scheduler | |
| import java.math.BigInteger | |
| import javax.annotation.concurrent.ThreadSafe | |
| import javax.inject.Inject | |
| import javax.inject.Singleton | |
| /** | |
| * Beware!! | |
| * | |
| * Cart operation must guarantees that no background execution outside of what is triggered | |
| * by user is happening. for example : calling [Cart.add] randomly by remote synchronization | |
| * | |
| * If you want to implement remote synchronization, it is advised to implement [CartStorage] | |
| * and used it only as initial syncing and save mechanism | |
| * | |
| * @see [CartStorage.loadCart] and [CartStorage.observeCartChanges] | |
| */ | |
| @ThreadSafe | |
| @Singleton | |
| class Cart @Inject constructor(cartStorage : CartStorage){ | |
| private val cartSubject = ThreadConfinedBehaviorSubject.createDefault<List<CartItem>>(emptyList()) | |
| private val cartInternalObserver = cartSubject.expose() | |
| .distinctUntilChanged() | |
| private val totalPriceObservable = cartInternalObserver | |
| .map { it.totalPrice } | |
| private val badgeObserver = cartInternalObserver | |
| .map { it.size } | |
| init { | |
| val initialCart = cartStorage.loadCart() | |
| cartSubject.update { onNext(initialCart) } | |
| /** | |
| * make cartSubject be source of truth for what cart contains of | |
| */ | |
| cartStorage.observeCartChanges(cartInternalObserver.share()) | |
| } | |
| fun observeOn(scheduler : Scheduler) = cartInternalObserver.share().observeOn(scheduler)!! | |
| fun observeBadgeCount() = badgeObserver.share()!! | |
| fun observeTotalPrice() = totalPriceObservable.share()!! | |
| fun add(item : CartItem) { | |
| cartSubject.update { onNext(value!! + item) } | |
| } | |
| fun changeItem(newItem : CartItem){ | |
| cartSubject.update { | |
| val cart = value!! | |
| val oldItem = cart.first { it.id == newItem.id } | |
| cart - oldItem + newItem | |
| } | |
| } | |
| fun removeItem(item : CartItem){ | |
| cartSubject.update { | |
| val cart = value!! | |
| cart - item | |
| } | |
| } | |
| } | |
| val List<CartItem>.totalPrice : BigInteger | |
| get() { | |
| return fold(BigInteger.ZERO){ acc, cartItem -> | |
| acc + cartItem.price | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import android.os.Bundle | |
| import android.view.View | |
| import com.myapplication.R | |
| import com.myapplication.domain.model.checkout.CartItem | |
| import com.myapplication.domain.model.checkout.cart.Cart | |
| import com.myapplication.domain.model.checkout.cart.totalPrice | |
| import com.myapplication.helper.date.DateFormat | |
| import com.myapplication.helper.fragment.DisposeOn | |
| import com.myapplication.helper.misc.PriceUtil | |
| import com.myapplication.helper.misc.dp | |
| import com.myapplication.helper.recyclerview.vertical | |
| import com.myapplication.presenter.base.AbstractFragment | |
| import com.myapplication.presenter.payment.checkout.adapter.CheckoutAdapter | |
| import dagger.hilt.android.AndroidEntryPoint | |
| import io.reactivex.Maybe | |
| import io.reactivex.android.schedulers.AndroidSchedulers | |
| import kotlinx.android.synthetic.main.checkout.* | |
| import kotlinx.android.synthetic.main.pricetotal_below.* | |
| import org.threeten.bp.LocalDate | |
| import javax.inject.Inject | |
| @AndroidEntryPoint | |
| class CheckoutFragment : AbstractFragment(R.layout.checkout) { | |
| @Inject lateinit var cart : Cart | |
| override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | |
| super.onViewCreated(view, savedInstanceState) | |
| checkout_products.vertical(10.dp) | |
| val adapter = CheckoutAdapter(this) | |
| checkout_products.adapter = adapter | |
| cart.observeOn(AndroidSchedulers.mainThread()).subscribe { | |
| checkout_total_price.text = PriceUtil.toRupiah(it.totalPrice) | |
| adapter.submitList(it) | |
| }.autoDispose(DisposeOn.VIEW_DESTROYED) | |
| cart_button.setOnClickListener { | |
| val action = CheckoutFragmentDirections.pay() | |
| navController.navigate(action) | |
| } | |
| checkout_date.text = requireContext().getString(R.string.checkout_date, DateFormat.defaultDate(LocalDate.now())) | |
| } | |
| inner class CartUpdateListener : CheckoutAdapter.CartUpdateListener{ | |
| override fun observeItemRemoved(itemObserver: Maybe<out CartItem>) { | |
| itemObserver.subscribe { | |
| cart.removeItem(it) | |
| }.autoDispose(DisposeOn.VIEW_DESTROYED) | |
| } | |
| override fun observeItemUpdate(itemObserver: Maybe<out CartItem>) { | |
| itemObserver.subscribe { | |
| cart.changeItem(it) | |
| }.autoDispose(DisposeOn.VIEW_DESTROYED) | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment