From e1e9ec07e18c3a2c49d5f5b2b6e3554ef4e01f53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BE=D0=BB=D0=BE=D0=B4=D1=8F?= <VladimirMorozov.73@yandex.ru> Date: Sat, 23 Dec 2023 08:19:43 +0300 Subject: [PATCH] lab 5 refactoring --- .../com/example/pizza/Model/Basket/Basket.kt | 8 +-- .../example/pizza/Model/Basket/BasketDao.kt | 2 +- .../com/example/pizza/Model/Dto/OrderDto.kt | 11 ++-- .../com/example/pizza/Model/Order/Order.kt | 14 ++--- .../com/example/pizza/Model/Order/OrderDao.kt | 12 ++-- .../example/pizza/Model/Order/PizzaOrder.kt | 2 +- .../com/example/pizza/Model/OrderAdapter.kt | 23 +++++--- .../Model/Repository/BasketRepository.kt | 2 +- .../Repository/OfflineBasketRepository.kt | 2 +- .../Repository/OfflineOrderRepository.kt | 2 +- .../Model/Repository/OfflineUserRepository.kt | 1 + .../pizza/Model/Repository/OrderRepository.kt | 2 +- .../Rest/Mediators/OrderRemoteMediator.kt | 39 ++++++++----- .../Repository/Rest/RestBasketRepository.kt | 56 +++++++++++-------- .../Repository/Rest/RestOrderRepository.kt | 19 ++++--- .../Repository/Rest/RestUserRepository.kt | 14 ++++- .../pizza/Model/Rest/MyServerService.kt | 15 ++--- .../com/example/pizza/Model/User/UserDao.kt | 3 +- .../pizza/ViewModels/BasketListViewModel.kt | 25 ++------- .../pizza/ViewModels/OrderEditViewModel.kt | 2 +- .../pizza/ViewModels/OrderListViewModel.kt | 37 ++++++------ app/src/main/java/com/example/pizza/crate.kt | 2 +- .../example/pizza/database/AppContainer.kt | 1 + .../com/example/pizza/database/AppDatabase.kt | 2 +- app/src/main/java/com/example/pizza/user.kt | 3 + 25 files changed, 171 insertions(+), 128 deletions(-) diff --git a/app/src/main/java/com/example/pizza/Model/Basket/Basket.kt b/app/src/main/java/com/example/pizza/Model/Basket/Basket.kt index 588f035..e16f2e4 100644 --- a/app/src/main/java/com/example/pizza/Model/Basket/Basket.kt +++ b/app/src/main/java/com/example/pizza/Model/Basket/Basket.kt @@ -14,14 +14,14 @@ import com.example.pizza.Model.User.User entity = Pizza::class, parentColumns = ["uid"], childColumns = ["pizza_id"], - onDelete = ForeignKey.RESTRICT, - onUpdate = ForeignKey.RESTRICT), + onDelete = ForeignKey.CASCADE, + onUpdate = ForeignKey.CASCADE), ForeignKey( entity = User::class, parentColumns = ["uid"], childColumns = ["user_id"], - onDelete = ForeignKey.RESTRICT, - onUpdate = ForeignKey.RESTRICT), + onDelete = ForeignKey.CASCADE, + onUpdate = ForeignKey.CASCADE), ], primaryKeys = ["user_id", "pizza_id"]) data class Basket( diff --git a/app/src/main/java/com/example/pizza/Model/Basket/BasketDao.kt b/app/src/main/java/com/example/pizza/Model/Basket/BasketDao.kt index 9241dbf..a8baa81 100644 --- a/app/src/main/java/com/example/pizza/Model/Basket/BasketDao.kt +++ b/app/src/main/java/com/example/pizza/Model/Basket/BasketDao.kt @@ -13,7 +13,7 @@ import io.reactivex.rxjava3.core.Flowable @Dao interface BasketDao { @Query("select * from basket inner join pizzas on basket.pizza_id = pizzas.uid where basket.user_id = :uid") - fun getUserBasket(uid: Int): RxPagingSource<Int, PizzaBasket> + fun getUserBasket(uid: Int): Flowable<List<PizzaBasket>> @Query("select * from basket inner join pizzas on basket.pizza_id = pizzas.uid where basket.user_id = :uid") fun getUserAllBasket(uid: Int): Flowable<List<PizzaBasket>> @Insert diff --git a/app/src/main/java/com/example/pizza/Model/Dto/OrderDto.kt b/app/src/main/java/com/example/pizza/Model/Dto/OrderDto.kt index 7c030e0..de8e961 100644 --- a/app/src/main/java/com/example/pizza/Model/Dto/OrderDto.kt +++ b/app/src/main/java/com/example/pizza/Model/Dto/OrderDto.kt @@ -3,15 +3,16 @@ package com.example.pizza.Model.Dto import com.example.pizza.Model.Order.Order import com.example.pizza.Model.Pizza.Pizza +import com.google.gson.annotations.SerializedName import kotlinx.serialization.Serializable import java.util.Date @Serializable data class OrderDto( - val uid : Int? = 0, - val date: Long = 0, - val pizza: Int? = 0, - val user: Int? = 0, - val price : Int = 0 + @SerializedName("id") val uid : Int?, + @SerializedName("date")val date: Long , + @SerializedName("pizza")val pizza: Int, + @SerializedName("user")val user: Int , + @SerializedName("price")val price : Int ) fun OrderDto.toOrder(): Order = Order( uid, Date(date), pizza, user, price) diff --git a/app/src/main/java/com/example/pizza/Model/Order/Order.kt b/app/src/main/java/com/example/pizza/Model/Order/Order.kt index 3268d2c..5b62411 100644 --- a/app/src/main/java/com/example/pizza/Model/Order/Order.kt +++ b/app/src/main/java/com/example/pizza/Model/Order/Order.kt @@ -17,14 +17,14 @@ import java.util.Date entity = Pizza::class, parentColumns = ["uid"], childColumns = ["pizza_id"], - onDelete = ForeignKey.RESTRICT, - onUpdate = ForeignKey.RESTRICT), + onDelete = ForeignKey.CASCADE, + onUpdate = ForeignKey.CASCADE), ForeignKey( entity = User::class, parentColumns = ["uid"], childColumns = ["user_id"], - onDelete = ForeignKey.RESTRICT, - onUpdate = ForeignKey.RESTRICT), + onDelete = ForeignKey.CASCADE, + onUpdate = ForeignKey.CASCADE), ]) @TypeConverters(DateConverter::class) class Order( @@ -33,9 +33,9 @@ class Order( @ColumnInfo(name = "date") val date: Date, @ColumnInfo(name = "pizza_id", index = true) - val pizza: Int? , + val pizza: Int , @ColumnInfo(name = "user_id", index = true) - val user: Int? , + val user: Int , val price : Int ) { @Ignore constructor( @@ -43,7 +43,7 @@ class Order( Pizza : Pizza, User : User, Price : Int - ) : this(null , Date, Pizza.uid, User.uid, Price) + ) : this(null , Date, Pizza.uid!!, User.uid!!, Price) override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false diff --git a/app/src/main/java/com/example/pizza/Model/Order/OrderDao.kt b/app/src/main/java/com/example/pizza/Model/Order/OrderDao.kt index f795922..f472584 100644 --- a/app/src/main/java/com/example/pizza/Model/Order/OrderDao.kt +++ b/app/src/main/java/com/example/pizza/Model/Order/OrderDao.kt @@ -4,6 +4,7 @@ import androidx.paging.rxjava3.RxPagingSource import androidx.room.Dao import androidx.room.Delete import androidx.room.Insert +import androidx.room.OnConflictStrategy import androidx.room.Query import androidx.room.Update import com.example.pizza.Model.Basket.Basket @@ -12,18 +13,21 @@ import io.reactivex.rxjava3.core.Flowable @Dao interface OrderDao { - @Query("select orders.date as date, group_concat(pizzas.pizza_title) as pizzas, Sum(orders.price) as price from orders" + - " join pizzas on orders.pizza_id = pizzas.uid where orders.user_id = :uid group by orders.date order by orders.date desc") + +// @Query("select orders.date as date, group_concat(pizzas.pizza_title) as pizzas, Sum(orders.price) as price from orders" + +// " join pizzas on orders.pizza_id = pizzas.uid where orders.user_id = :uid group by orders.date order by orders.date desc") +@Query("select orders.uid as uid, orders.date as date, pizzas.pizza_title as pizzas, orders.price as price from orders" + + " join pizzas on orders.pizza_id = pizzas.uid where orders.user_id = :uid ") fun getUserHistory(uid: Int): RxPagingSource<Int, PizzaOrder> @Insert fun insert(group: Order): Completable @Delete fun delete(group: Order): Completable - @Query("DELETE FROM pizzas") + @Query("DELETE FROM orders") fun deleteAll(): Completable @Insert - fun insertMany(group: List<Order>): Completable + fun insertAll(group: List<Order>): Completable } \ No newline at end of file diff --git a/app/src/main/java/com/example/pizza/Model/Order/PizzaOrder.kt b/app/src/main/java/com/example/pizza/Model/Order/PizzaOrder.kt index ddd0042..25bad0f 100644 --- a/app/src/main/java/com/example/pizza/Model/Order/PizzaOrder.kt +++ b/app/src/main/java/com/example/pizza/Model/Order/PizzaOrder.kt @@ -2,5 +2,5 @@ package com.example.pizza.Model.Order import java.util.Date -class PizzaOrder(val date: Date, val pizzas : String, val price : Int) { +class PizzaOrder(val uid: Int,val date: Date, val pizzas : String, val price : Int) { } \ No newline at end of file diff --git a/app/src/main/java/com/example/pizza/Model/OrderAdapter.kt b/app/src/main/java/com/example/pizza/Model/OrderAdapter.kt index 21302fb..b861201 100644 --- a/app/src/main/java/com/example/pizza/Model/OrderAdapter.kt +++ b/app/src/main/java/com/example/pizza/Model/OrderAdapter.kt @@ -7,6 +7,9 @@ import android.view.View import android.view.ViewGroup import android.widget.Button import android.widget.TextView +import androidx.lifecycle.LiveData +import androidx.lifecycle.map +import androidx.paging.PagingData import androidx.paging.PagingDataAdapter import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView @@ -51,7 +54,7 @@ class OrderAdapter( var context: Context, val resSum: TextView, val basketVm : B holder.count.text = it.count_pizza.toString() holder.sum.text = it.pizza_price.toString() resSum.text = (resSum.text.toString().toInt() + it.pizza_price).toString() - holder.btnTrash.setOnClickListener{deleteFromBasket(holder,position)} + holder.btnTrash.setOnClickListener{deleteFromBasket(holder,pizza.user_id,pizza.pizza_id,pizza.pizza_price)} } @@ -61,7 +64,8 @@ class OrderAdapter( var context: Context, val resSum: TextView, val basketVm : B return getItem(position) } - fun btnPlus(holder:MyViewHolder,position: Int){ + @SuppressLint("SetTextI18n") + fun btnPlus(holder:MyViewHolder, position: Int){ val pizza = getItem(position) pizza?.let { var count = holder.count.text.toString().toInt() @@ -85,15 +89,16 @@ class OrderAdapter( var context: Context, val resSum: TextView, val basketVm : B } } - @SuppressLint("CheckResult") - fun deleteFromBasket(holder: OrderAdapter.MyViewHolder, position: Int){ - val pizza = getItem(position) - val price = pizza!!.pizza_price + @SuppressLint("CheckResult", "NotifyDataSetChanged") + fun deleteFromBasket(holder: OrderAdapter.MyViewHolder, uid:Int,pid:Int,price:Int){ val count = holder.count.text.toString().toInt() val sum = price*count - basketVm.deletePizza(pizza!!.user_id,pizza!!.pizza_id) - { val oldSum = resSum.text.toString().toInt() + basketVm.deletePizza(uid,pid) + { + val oldSum = resSum.text.toString().toInt() val newSum = oldSum - sum - resSum.text = newSum.toString()} + resSum.text = newSum.toString() + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/pizza/Model/Repository/BasketRepository.kt b/app/src/main/java/com/example/pizza/Model/Repository/BasketRepository.kt index 88a3f5c..bdb03c6 100644 --- a/app/src/main/java/com/example/pizza/Model/Repository/BasketRepository.kt +++ b/app/src/main/java/com/example/pizza/Model/Repository/BasketRepository.kt @@ -7,7 +7,7 @@ import io.reactivex.rxjava3.core.Completable import io.reactivex.rxjava3.core.Flowable interface BasketRepository { - fun getUserBasket(uid: Int): RxPagingSource<Int, PizzaBasket> + fun getUserBasket(uid: Int): Flowable<List<PizzaBasket>> fun insert(group: Basket): Completable fun getUserAllBasket(uid: Int): Flowable<List<PizzaBasket>> diff --git a/app/src/main/java/com/example/pizza/Model/Repository/OfflineBasketRepository.kt b/app/src/main/java/com/example/pizza/Model/Repository/OfflineBasketRepository.kt index 008c4c4..dabcb63 100644 --- a/app/src/main/java/com/example/pizza/Model/Repository/OfflineBasketRepository.kt +++ b/app/src/main/java/com/example/pizza/Model/Repository/OfflineBasketRepository.kt @@ -9,7 +9,7 @@ import io.reactivex.rxjava3.core.Completable import io.reactivex.rxjava3.core.Flowable class OfflineBasketRepository(private val basketDao : BasketDao) : BasketRepository { - override fun getUserBasket(uid: Int): RxPagingSource<Int, PizzaBasket> = basketDao.getUserBasket(uid) + override fun getUserBasket(uid: Int): Flowable<List<PizzaBasket>> = basketDao.getUserBasket(uid) override fun getUserAllBasket(uid: Int): Flowable<List<PizzaBasket>> = basketDao.getUserAllBasket(uid) override fun insert(group: Basket): Completable = basketDao.insert(group) diff --git a/app/src/main/java/com/example/pizza/Model/Repository/OfflineOrderRepository.kt b/app/src/main/java/com/example/pizza/Model/Repository/OfflineOrderRepository.kt index b8ef04b..f2ddbd1 100644 --- a/app/src/main/java/com/example/pizza/Model/Repository/OfflineOrderRepository.kt +++ b/app/src/main/java/com/example/pizza/Model/Repository/OfflineOrderRepository.kt @@ -12,7 +12,7 @@ class OfflineOrderRepository(private val orderDao: OrderDao) : OrderRepository { override fun insert(group: Order): Completable = orderDao.insert(group) - override fun insertMany(group: List<Order>): Completable = orderDao.insertMany(group) + override fun insertAll(group: List<Order>): Completable = orderDao.insertAll(group) fun delete(group: Order): Completable = orderDao.delete(group) fun deleteAll(): Completable = orderDao.deleteAll() } \ No newline at end of file diff --git a/app/src/main/java/com/example/pizza/Model/Repository/OfflineUserRepository.kt b/app/src/main/java/com/example/pizza/Model/Repository/OfflineUserRepository.kt index 3e2cfdd..f7f6d86 100644 --- a/app/src/main/java/com/example/pizza/Model/Repository/OfflineUserRepository.kt +++ b/app/src/main/java/com/example/pizza/Model/Repository/OfflineUserRepository.kt @@ -16,6 +16,7 @@ class OfflineUserRepository(private val userDao : UserDao) : UserRepository { override fun getByLoginAndPassword(login: String, pass: String): Single<User> = userDao.getByLoginAndPassword(login,pass) override fun insert(group: User): Completable = userDao.insert(group) + fun deleteAll(): Completable = userDao.deleteAll() override fun update(group: User): Completable = userDao.update(group) diff --git a/app/src/main/java/com/example/pizza/Model/Repository/OrderRepository.kt b/app/src/main/java/com/example/pizza/Model/Repository/OrderRepository.kt index d497bc2..7a17e9e 100644 --- a/app/src/main/java/com/example/pizza/Model/Repository/OrderRepository.kt +++ b/app/src/main/java/com/example/pizza/Model/Repository/OrderRepository.kt @@ -11,5 +11,5 @@ interface OrderRepository { fun insert(group: Order): Completable - fun insertMany(group: List<Order>): Completable + fun insertAll(group: List<Order>): Completable } \ No newline at end of file diff --git a/app/src/main/java/com/example/pizza/Model/Repository/Rest/Mediators/OrderRemoteMediator.kt b/app/src/main/java/com/example/pizza/Model/Repository/Rest/Mediators/OrderRemoteMediator.kt index 98aa94e..ad60845 100644 --- a/app/src/main/java/com/example/pizza/Model/Repository/Rest/Mediators/OrderRemoteMediator.kt +++ b/app/src/main/java/com/example/pizza/Model/Repository/Rest/Mediators/OrderRemoteMediator.kt @@ -10,17 +10,22 @@ import androidx.paging.LoadType import androidx.paging.PagingState import androidx.paging.RemoteMediator import androidx.paging.rxjava3.RxRemoteMediator +import com.example.pizza.Model.Dto.UserDto import com.example.pizza.Model.Dto.toOrder import com.example.pizza.Model.Dto.toPizza +import com.example.pizza.Model.Dto.toUser import com.example.pizza.Model.Order.Order +import com.example.pizza.Model.Order.PizzaOrder import com.example.pizza.Model.Pizza.Pizza import com.example.pizza.Model.Repository.OfflineOrderRepository import com.example.pizza.Model.Repository.OfflinePizzaRepository +import com.example.pizza.Model.Repository.OfflineUserRepository import com.example.pizza.Model.Rest.MyServerService import com.example.pizza.RemoteKeys.OfflineRemoteKeyRepository import com.example.pizza.RemoteKeys.RemoteKeyType import com.example.pizza.RemoteKeys.RemoteKeys import com.example.pizza.database.AppDatabase +import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.core.Maybe import io.reactivex.rxjava3.core.Observable import io.reactivex.rxjava3.core.Single @@ -36,11 +41,11 @@ class OrderRemoteMediator( private val dbRemoteKeyRepository: OfflineRemoteKeyRepository, private val database: AppDatabase, private val id : Int -): RxRemoteMediator<Int, Order>() { +): RxRemoteMediator<Int, PizzaOrder>() { @RequiresApi(Build.VERSION_CODES.O) override fun loadSingle( loadType: LoadType, - state: PagingState<Int, Order> + state: PagingState<Int, PizzaOrder> ): Single<MediatorResult> { Log.d(this::class.simpleName, state.toString()) @@ -86,26 +91,34 @@ class OrderRemoteMediator( @SuppressLint("CheckResult") @RequiresApi(Build.VERSION_CODES.O) - fun getMediatorResout(loadType: LoadType, page : AtomicInteger, state: PagingState<Int, Order>) + fun getMediatorResout(loadType: LoadType, page : AtomicInteger, state: PagingState<Int, PizzaOrder>) : Single<MediatorResult> { - Log.d(PizzaRemoteMediator::class.simpleName,"Load") - service.getAllPizzas() + Log.d(OrderRemoteMediator::class.simpleName,"Load") + return service.getAllPizzas() .subscribeOn(Schedulers.io()) - .map{ + .map { + if(loadType == LoadType.REFRESH){ database.runInTransaction { + dbPizzaRepository.deleteAll().blockingAwait() + Log.d(OrderRemoteMediator::class.simpleName,"pizzas deleted") + dbPizzaRepository.insertAll(it.map { it.toPizza() }).blockingAwait() + Log.d(OrderRemoteMediator::class.simpleName,"pizzas loaded ${it.size}") } - dbPizzaRepository.insertAll(it.map { it.toPizza() }).blockingAwait() + } - return service.getUserOrders(id,state.config.pageSize,(page.get()-1)*state.config.pageSize) - .subscribeOn(Schedulers.io()) + } + .flatMap { service.getUserOrders(id,state.config.pageSize,(page.get()-1)*state.config.pageSize) } .map{ database.runInTransaction { if(loadType == LoadType.REFRESH) { dbOrderRepository.deleteAll().blockingAwait() dbRemoteKeyRepository.deleteRemoteKey(RemoteKeyType.ORDER).blockingAwait() + Log.d(OrderRemoteMediator::class.simpleName,"orders deleted") + } - dbOrderRepository.insertMany(it.map { it.toOrder() }).blockingAwait() + Log.d(OrderRemoteMediator::class.simpleName,"start load orders") + dbOrderRepository.insertAll(it.map { it.toOrder() }).blockingAwait() val prevKey = if (page.get() == 1) null else page.get() - 1 val nextKey = if (it.isEmpty()) null else page.get() + 1 val keys = it.map { @@ -125,21 +138,21 @@ class OrderRemoteMediator( Single.just(MediatorResult.Error(e) as MediatorResult) } } - private fun getRemoteKeyForLastItem(state: PagingState<Int, Order>): Maybe<RemoteKeys> { + private fun getRemoteKeyForLastItem(state: PagingState<Int, PizzaOrder>): Maybe<RemoteKeys> { return state.pages.lastOrNull { it.data.isNotEmpty() }?.data?.lastOrNull() ?.let { group -> dbRemoteKeyRepository.getAllRemoteKeys(group.uid!!, RemoteKeyType.ORDER) } ?: Maybe.empty() } - private fun getRemoteKeyForFirstItem(state: PagingState<Int, Order>): Maybe<RemoteKeys> { + private fun getRemoteKeyForFirstItem(state: PagingState<Int, PizzaOrder>): Maybe<RemoteKeys> { return state.pages.firstOrNull { it.data.isNotEmpty() }?.data?.firstOrNull() ?.let { group -> dbRemoteKeyRepository.getAllRemoteKeys(group.uid!!, RemoteKeyType.ORDER) }?: Maybe.empty() } - private fun getRemoteKeyClosestToCurrentPosition( state: PagingState<Int, Order>): Maybe<RemoteKeys> { + private fun getRemoteKeyClosestToCurrentPosition( state: PagingState<Int, PizzaOrder>): Maybe<RemoteKeys> { return state.anchorPosition?.let { position -> state.closestItemToPosition(position)?.uid?.let { studentUid -> dbRemoteKeyRepository.getAllRemoteKeys(studentUid, RemoteKeyType.ORDER) diff --git a/app/src/main/java/com/example/pizza/Model/Repository/Rest/RestBasketRepository.kt b/app/src/main/java/com/example/pizza/Model/Repository/Rest/RestBasketRepository.kt index 5f4f4ce..3fd3d7a 100644 --- a/app/src/main/java/com/example/pizza/Model/Repository/Rest/RestBasketRepository.kt +++ b/app/src/main/java/com/example/pizza/Model/Repository/Rest/RestBasketRepository.kt @@ -12,6 +12,7 @@ import com.example.pizza.Model.Dto.BasketDto import com.example.pizza.Model.Dto.toBasket import com.example.pizza.Model.Dto.toBasketDto import com.example.pizza.Model.Dto.toPizza +import com.example.pizza.Model.Dto.toUser import com.example.pizza.Model.Dto.toUserDto import com.example.pizza.Model.Pizza.Pizza import com.example.pizza.Model.Repository.BasketRepository @@ -30,32 +31,35 @@ import okhttp3.internal.wait class RestBasketRepository(private val service: MyServerService, private val dbBasketRepository: OfflineBasketRepository, private val dbPizzaRepository: OfflinePizzaRepository, + private val dbUserRepository: OfflineUserRepository, private val dbRemoteKeyRepository: OfflineRemoteKeyRepository, private val database: AppDatabase ) : BasketRepository { - var AllBaskets : MutableLiveData<RxPagingSource<Int, PizzaBasket>?> = MutableLiveData() @RequiresApi(Build.VERSION_CODES.O) @SuppressLint("CheckResult") - override fun getUserBasket(uid: Int): RxPagingSource<Int, PizzaBasket> { - insertAll(uid) - return AllBaskets.value!! - } - @RequiresApi(Build.VERSION_CODES.O) - @SuppressLint("CheckResult") - fun insertAll(uid: Int){ + override fun getUserBasket(uid: Int): Flowable<List<PizzaBasket>> { Log.d("RestBasketRepository", "Insert All") - Observable.zip(service.getUserBaskets(uid),service.getAllPizzas()){ - baskets,pizzas -> - Log.d("RestBasketRepository", "Insert All") - val bks = baskets.map { it.toBasket() } - val ps = pizzas.map { it.toPizza() } - database.runInTransaction{ - dbBasketRepository.deleteAll().blockingAwait() - dbPizzaRepository.deleteAll().blockingAwait() - dbBasketRepository.insertAll(bks).blockingAwait() - dbPizzaRepository.insertAll(ps).blockingAwait() + var fff = service.getAllPizzas() + .map{data -> + val ps = data.map { it.toPizza() } + database.runInTransaction{ + dbPizzaRepository.deleteAll().blockingAwait() + dbPizzaRepository.insertAll(ps).blockingAwait() + Log.d("RestBasketRepository", ps.toString()) + } } - }.map { dbBasketRepository.getUserBasket(uid) }.subscribe { data -> AllBaskets.postValue(data)} + .flatMap { service.getUserBaskets(uid) } + .map{data -> + val bks = data.map { it.toBasket() } + database.runInTransaction{ + dbBasketRepository.deleteAll().blockingAwait() + dbBasketRepository.insertAll(bks).blockingAwait() + Log.d("RestBasketRepository", bks.toString()) + } + } + .flatMap { dbBasketRepository.getUserBasket(uid) } + + return fff } @SuppressLint("CheckResult") @@ -72,9 +76,15 @@ class RestBasketRepository(private val service: MyServerService, throw Exception() } - override fun deleteByUser(uid: Int): Completable = Completable.fromObservable(service.deleteUserBaskets(uid)) + @SuppressLint("CheckResult") + override fun deleteByUser(uid: Int): Completable { - override fun deleteByUserAndPizza(uid: Int, pid: Int): Completable = Completable.fromObservable(service.deleteBasket( - BasketDto(uid,pid,1) - )) + return Completable.fromObservable(service.deleteUserBaskets(uid)).andThen { dbBasketRepository.deleteByUser(uid).blockingAwait() } + } + + @SuppressLint("CheckResult") + override fun deleteByUserAndPizza(uid: Int, pid: Int): Completable { + return Completable.fromObservable( service.deleteBasket(uid, pid)).andThen {dbBasketRepository.deleteByUserAndPizza(uid, pid).blockingAwait() } + + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/pizza/Model/Repository/Rest/RestOrderRepository.kt b/app/src/main/java/com/example/pizza/Model/Repository/Rest/RestOrderRepository.kt index b8a6626..ec367d5 100644 --- a/app/src/main/java/com/example/pizza/Model/Repository/Rest/RestOrderRepository.kt +++ b/app/src/main/java/com/example/pizza/Model/Repository/Rest/RestOrderRepository.kt @@ -1,14 +1,18 @@ package com.example.pizza.Model.Repository.Rest -import android.database.Observable +import android.annotation.SuppressLint +import android.os.Build +import androidx.annotation.RequiresApi import androidx.paging.rxjava3.RxPagingSource import androidx.room.Index import com.example.pizza.Model.Dto.OrderDto import com.example.pizza.Model.Dto.toOrderDto +import com.example.pizza.Model.Dto.toPizza import com.example.pizza.Model.Order.Order import com.example.pizza.Model.Order.PizzaOrder import com.example.pizza.Model.Repository.OfflineOrderRepository import com.example.pizza.Model.Repository.OfflinePizzaRepository +import com.example.pizza.Model.Repository.OfflineUserRepository import com.example.pizza.Model.Repository.OrderRepository import com.example.pizza.Model.Repository.Rest.Mediators.OrderRemoteMediator import com.example.pizza.Model.Repository.Rest.Mediators.PizzaRemoteMediator @@ -16,6 +20,7 @@ import com.example.pizza.Model.Rest.MyServerService import com.example.pizza.RemoteKeys.OfflineRemoteKeyRepository import com.example.pizza.database.AppDatabase import io.reactivex.rxjava3.core.Completable +import io.reactivex.rxjava3.schedulers.Schedulers class RestOrderRepository(private val service: MyServerService, private val dbOrderRepository: OfflineOrderRepository, @@ -24,8 +29,11 @@ class RestOrderRepository(private val service: MyServerService, private val database: AppDatabase ) : OrderRepository { var mediator: OrderRemoteMediator? = null + @RequiresApi(Build.VERSION_CODES.O) + @SuppressLint("CheckResult") override fun getUserHistory(uid: Int): RxPagingSource<Int, PizzaOrder> { if (mediator==null){ + mediator = OrderRemoteMediator( service, dbOrderRepository, @@ -34,6 +42,7 @@ class RestOrderRepository(private val service: MyServerService, database, uid ) + } return dbOrderRepository.getUserHistory(uid) @@ -41,13 +50,9 @@ class RestOrderRepository(private val service: MyServerService, override fun insert(group: Order): Completable = Completable.fromObservable(service.createOrder(group.toOrderDto())) - override fun insertMany(orders: List<Order>): Completable + override fun insertAll(group: List<Order>): Completable { - var list : MutableList <OrderDto> = mutableListOf<OrderDto>() - for (order in orders){ - - list.add(order.toOrderDto()) - } + var list = group.map{it.toOrderDto()} return Completable.fromObservable(service.createOrders(list)) } diff --git a/app/src/main/java/com/example/pizza/Model/Repository/Rest/RestUserRepository.kt b/app/src/main/java/com/example/pizza/Model/Repository/Rest/RestUserRepository.kt index 5ea07e9..12fe654 100644 --- a/app/src/main/java/com/example/pizza/Model/Repository/Rest/RestUserRepository.kt +++ b/app/src/main/java/com/example/pizza/Model/Repository/Rest/RestUserRepository.kt @@ -25,12 +25,22 @@ class RestUserRepository ( private val database: AppDatabase ) : UserRepository { @SuppressLint("CheckResult") - override fun getById(uid: Int): Single<User> = service.getUser(uid).map { it.toUser() } + override fun getById(uid: Int): Single<User> = service.getUser(uid).map { + Log.d(RestUserRepository::class.simpleName ,"load user by id") + database.runInTransaction{ + dbUserRepository.deleteAll().blockingAwait() + dbUserRepository.insert(it.toUser()).blockingAwait() + } + it.toUser() } override fun getByLoginAndPassword(login: String, pass: String): Single<User> { return service.getUserLP(login, pass).map { - Log.d(RestUserRepository::class.simpleName ,it.toString()) + Log.d(RestUserRepository::class.simpleName ,"load user by lp") + database.runInTransaction{ + dbUserRepository.deleteAll().blockingAwait() + dbUserRepository.insert(it.toUser()).blockingAwait() + } it.toUser() } } override fun insert(group: User): Completable = Completable.fromObservable(service.createUser(group.toUserDto())) diff --git a/app/src/main/java/com/example/pizza/Model/Rest/MyServerService.kt b/app/src/main/java/com/example/pizza/Model/Rest/MyServerService.kt index c8738b8..d121ebc 100644 --- a/app/src/main/java/com/example/pizza/Model/Rest/MyServerService.kt +++ b/app/src/main/java/com/example/pizza/Model/Rest/MyServerService.kt @@ -34,12 +34,12 @@ interface MyServerService { ): Flowable<List<PizzaDto>> @GET("allpizzas") fun getAllPizzas( - ): Observable<List<PizzaDto>> + ): Flowable<List<PizzaDto>> @GET("baskets/{id}") fun getUserBaskets( @Path("id") id: Int, - ): Observable<List<BasketDto>> + ): Flowable<List<BasketDto>> @GET("pizza/{id}") fun getPizza( @@ -51,9 +51,9 @@ interface MyServerService { @GET("orders/{id}") fun getUserOrders( @Path("id") id: Int, - @Query("page") page: Int, - @Query("size") limit: Int, - ): Observable<List<OrderDto>> + @Query("limit") limit: Int, + @Query("offset") offset: Int, + ): Flowable<List<OrderDto>> @GET("orders") fun getAllOrders( ): Observable<List<OrderDto>> @@ -110,11 +110,12 @@ interface MyServerService { @DELETE("baskets/{id}") fun deleteUserBaskets( @Path("id") id: Int, - ): Observable<BasketDto> + ): Observable<List<BasketDto>> @DELETE("basket") fun deleteBasket( - @Body user: BasketDto, + @Query("uid") uid : Int , + @Query("pid") pid : Int ): Observable<BasketDto> companion object { diff --git a/app/src/main/java/com/example/pizza/Model/User/UserDao.kt b/app/src/main/java/com/example/pizza/Model/User/UserDao.kt index 058e6df..201a949 100644 --- a/app/src/main/java/com/example/pizza/Model/User/UserDao.kt +++ b/app/src/main/java/com/example/pizza/Model/User/UserDao.kt @@ -26,7 +26,8 @@ interface UserDao { @Update fun update(group: User): Completable - + @Query("DELETE FROM users") + fun deleteAll(): Completable @Delete fun delete(group: User): Completable } \ No newline at end of file diff --git a/app/src/main/java/com/example/pizza/ViewModels/BasketListViewModel.kt b/app/src/main/java/com/example/pizza/ViewModels/BasketListViewModel.kt index db685c2..e687313 100644 --- a/app/src/main/java/com/example/pizza/ViewModels/BasketListViewModel.kt +++ b/app/src/main/java/com/example/pizza/ViewModels/BasketListViewModel.kt @@ -34,7 +34,7 @@ class BasketListViewModel(private val basketRepository: BasketRepository): ViewM } @SuppressLint("CheckResult") fun getAllBaskets(uid : Int, onLoad: (data : List<PizzaBasket>) -> Unit, onError: () -> Unit){ - basketRepository.getUserAllBasket(uid) + basketRepository.getUserBasket(uid) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { data -> @@ -42,31 +42,18 @@ class BasketListViewModel(private val basketRepository: BasketRepository): ViewM },{onError()}) } - private fun createPagingConfig(): PagingConfig { - val pageSize = 5 - val placeholders = true - return PagingConfig( - pageSize, - pageSize, - placeholders, - pageSize * 2, - pageSize + pageSize * 2, Int.MIN_VALUE - ) - } + @OptIn(ExperimentalCoroutinesApi::class) private fun loadPizzas(uid: Int) { - val disposable = Pager( - config = createPagingConfig(), - pagingSourceFactory = {basketRepository.getUserBasket(uid)} - ).flowable - .cachedIn(viewModelScope) + val disposable = basketRepository.getUserBasket(uid) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .doOnError({pizzas.value = null}) .subscribe { data -> - pizzas.postValue(data) + val ps = PagingData.from<PizzaBasket>(data) + pizzas.postValue(ps) } mDisposable.add(disposable) } @@ -75,7 +62,7 @@ class BasketListViewModel(private val basketRepository: BasketRepository): ViewM val disposable = basketRepository.deleteByUserAndPizza(uid,pid) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(onDelete) + .subscribe { onDelete() } mDisposable.add(disposable) } fun deleteAllPizza(uid:Int) { diff --git a/app/src/main/java/com/example/pizza/ViewModels/OrderEditViewModel.kt b/app/src/main/java/com/example/pizza/ViewModels/OrderEditViewModel.kt index e7a92cf..0678a72 100644 --- a/app/src/main/java/com/example/pizza/ViewModels/OrderEditViewModel.kt +++ b/app/src/main/java/com/example/pizza/ViewModels/OrderEditViewModel.kt @@ -19,7 +19,7 @@ class OrderEditViewModel( fun savePizza(pizzas: List<Order>, onSave: () -> Unit) { - val completable: Completable = orderRepository.insertMany(pizzas) + val completable: Completable = orderRepository.insertAll(pizzas) val disposable = completable .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) diff --git a/app/src/main/java/com/example/pizza/ViewModels/OrderListViewModel.kt b/app/src/main/java/com/example/pizza/ViewModels/OrderListViewModel.kt index 9cb9c61..73a5b86 100644 --- a/app/src/main/java/com/example/pizza/ViewModels/OrderListViewModel.kt +++ b/app/src/main/java/com/example/pizza/ViewModels/OrderListViewModel.kt @@ -1,5 +1,7 @@ package com.example.pizza.ViewModels +import android.os.Build +import androidx.annotation.RequiresApi import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel @@ -8,12 +10,9 @@ import androidx.paging.ExperimentalPagingApi import androidx.paging.Pager import androidx.paging.PagingConfig import androidx.paging.PagingData -import androidx.paging.PagingSource import androidx.paging.rxjava3.cachedIn import androidx.paging.rxjava3.flowable -import com.example.pizza.Model.Basket.PizzaBasket import com.example.pizza.Model.Order.PizzaOrder -import com.example.pizza.Model.Repository.BasketRepository import com.example.pizza.Model.Repository.OrderRepository import com.example.pizza.Model.Repository.Rest.RestOrderRepository import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers @@ -25,7 +24,7 @@ class OrderListViewModel(private val orderRepository: OrderRepository): ViewMode private val mDisposable = CompositeDisposable() private val pizzas: MutableLiveData<PagingData<PizzaOrder>?> = MutableLiveData() - + @RequiresApi(Build.VERSION_CODES.O) fun getPizzas(uid: Int): LiveData<PagingData<PizzaOrder>?> { loadPizzas(uid) return pizzas @@ -34,26 +33,28 @@ class OrderListViewModel(private val orderRepository: OrderRepository): ViewMode @OptIn(ExperimentalCoroutinesApi::class, ExperimentalPagingApi::class) + @RequiresApi(Build.VERSION_CODES.O) private fun loadPizzas(uid: Int) { - val pageSize = 3 + val pageSize = 10 val placeholders = true var config = PagingConfig( pageSize = pageSize, enablePlaceholders =placeholders ) -// val disposable = Pager( -// config = config, -// remoteMediator = (orderRepository as RestOrderRepository).mediator, -// pagingSourceFactory = { orderRepository.getUserHistory(uid) } -// ).flowable -// .cachedIn(viewModelScope) -// .subscribeOn(Schedulers.io()) -// .observeOn(AndroidSchedulers.mainThread()) -// .doOnError({pizzas.value = null}) -// .subscribe { data -> -// pizzas.postValue(data) -// } -// mDisposable.add(disposable) + val disposable = Pager( + config = config, + pagingSourceFactory = {orderRepository.getUserHistory(uid)}, + remoteMediator = (orderRepository as RestOrderRepository).mediator + + ).flowable + .cachedIn(viewModelScope) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .doOnError({pizzas.value = null}) + .subscribe { data -> + pizzas.postValue(data) + } + mDisposable.add(disposable) } override fun onCleared() { diff --git a/app/src/main/java/com/example/pizza/crate.kt b/app/src/main/java/com/example/pizza/crate.kt index 36fee1a..af46496 100644 --- a/app/src/main/java/com/example/pizza/crate.kt +++ b/app/src/main/java/com/example/pizza/crate.kt @@ -101,7 +101,7 @@ class crate : Fragment() { val child = itemsList.getChildAt(i) val price = child.findViewById<TextView>(R.id.order_sum).text.toString().toInt() list.add(Order(null, currentDate, listPizzas.get(i).pizza_id, - viewModel.getId(), price)) + viewModel.getId()!!, price)) } basketVM!!.deleteAllPizza(viewModel.getId()!!) orderViewModel!!.savePizza(list){ diff --git a/app/src/main/java/com/example/pizza/database/AppContainer.kt b/app/src/main/java/com/example/pizza/database/AppContainer.kt index a179370..3c63924 100644 --- a/app/src/main/java/com/example/pizza/database/AppContainer.kt +++ b/app/src/main/java/com/example/pizza/database/AppContainer.kt @@ -47,6 +47,7 @@ class AppDataContainer(private val context: Context) : AppContainer { MyServerService.getInstance(), OfflineBasketRepository(AppDatabase.getInstance(context).basketDao()), OfflinePizzaRepository(AppDatabase.getInstance(context).pizzaDao()), + OfflineUserRepository(AppDatabase.getInstance(context).userDao()), OfflineRemoteKeyRepository(AppDatabase.getInstance(context).remoteKeysDao()), AppDatabase.getInstance(context)) } diff --git a/app/src/main/java/com/example/pizza/database/AppDatabase.kt b/app/src/main/java/com/example/pizza/database/AppDatabase.kt index eff8c65..10604f3 100644 --- a/app/src/main/java/com/example/pizza/database/AppDatabase.kt +++ b/app/src/main/java/com/example/pizza/database/AppDatabase.kt @@ -49,7 +49,7 @@ abstract class AppDatabase : RoomDatabase() { abstract fun orderDao(): OrderDao abstract fun remoteKeysDao(): RemoteKeysDao companion object { - private const val DB_NAME: String = "dp11" + private const val DB_NAME: String = "dp14" @Volatile private var INSTANCE: AppDatabase? = null diff --git a/app/src/main/java/com/example/pizza/user.kt b/app/src/main/java/com/example/pizza/user.kt index 254aaa7..b0a13d0 100644 --- a/app/src/main/java/com/example/pizza/user.kt +++ b/app/src/main/java/com/example/pizza/user.kt @@ -1,6 +1,7 @@ package com.example.pizza import android.annotation.SuppressLint +import android.os.Build import android.os.Bundle import androidx.fragment.app.Fragment import android.view.LayoutInflater @@ -9,6 +10,7 @@ import android.view.ViewGroup import android.widget.Button import android.widget.TextView import android.widget.Toast +import androidx.annotation.RequiresApi import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels import androidx.lifecycle.LiveData @@ -51,6 +53,7 @@ class user : Fragment() { ) orderViewModel = viewModel2 } + @RequiresApi(Build.VERSION_CODES.O) override fun onStart() { super.onStart() val pizzas: LiveData<PagingData<PizzaOrder>?>? = orderViewModel?.getPizzas(viewModel.getId()!!)