Feature: add pagging, connect to API

This commit is contained in:
Emelyanov535 2023-12-07 00:20:08 +04:00
parent 2f99f363c0
commit 6b41efd82e
23 changed files with 495 additions and 50 deletions

View File

@ -2,6 +2,7 @@ plugins {
id("com.android.application") id("com.android.application")
id("org.jetbrains.kotlin.android") id("org.jetbrains.kotlin.android")
id ("kotlin-kapt") id ("kotlin-kapt")
kotlin("plugin.serialization") version "1.4.21"
} }
android { android {

View File

@ -1,13 +1,20 @@
package com.example.android_programming package com.example.android_programming
import com.example.android_programming.api.repository.RestSneakerRepository
import com.example.android_programming.api.repository.RestUserRepository
import com.example.android_programming.repository.BasketRepository import com.example.android_programming.repository.BasketRepository
import com.example.android_programming.repository.OrderRepository import com.example.android_programming.repository.OrderRepository
import com.example.android_programming.repository.SneakerRepository import com.example.android_programming.repository.SneakerRepository
import com.example.android_programming.repository.UserRepository import com.example.android_programming.repository.UserRepository
interface AppContainer { interface AppContainer {
val sneakerRepo: SneakerRepository val sneakerRepo: RestSneakerRepository
val userRepo: UserRepository val userRepo: RestUserRepository
val orderRepo: OrderRepository val orderRepo: OrderRepository
val basketRepo: BasketRepository val basketRepo: BasketRepository
companion object {
const val TIMEOUT = 5000L
const val LIMIT = 10
}
} }

View File

@ -1,7 +1,11 @@
package com.example.android_programming package com.example.android_programming
import android.content.Context import android.content.Context
import com.example.android_programming.api.BackendService
import com.example.android_programming.api.repository.RestSneakerRepository
import com.example.android_programming.api.repository.RestUserRepository
import com.example.android_programming.database.AppDatabase import com.example.android_programming.database.AppDatabase
import com.example.android_programming.database.remotekeys.repository.RemoteKeysRepositoryImpl
import com.example.android_programming.repository.BasketRepoImpl import com.example.android_programming.repository.BasketRepoImpl
import com.example.android_programming.repository.BasketRepository import com.example.android_programming.repository.BasketRepository
import com.example.android_programming.repository.OrderRepoImpl import com.example.android_programming.repository.OrderRepoImpl
@ -12,11 +16,16 @@ import com.example.android_programming.repository.UserRepoImpl
import com.example.android_programming.repository.UserRepository import com.example.android_programming.repository.UserRepository
class AppDataContainer(private val context: Context) : AppContainer { class AppDataContainer(private val context: Context) : AppContainer {
override val sneakerRepo: SneakerRepository by lazy { override val sneakerRepo: RestSneakerRepository by lazy {
SneakerRepoImpl(AppDatabase.getInstance(context).sneakerDao()) RestSneakerRepository(
BackendService.getInstance(),
sneakerRepository,
AppDatabase.getInstance(context),
remoteKeyRepository
)
} }
override val userRepo: UserRepository by lazy { override val userRepo: RestUserRepository by lazy {
UserRepoImpl(AppDatabase.getInstance(context).userDao()) RestUserRepository(BackendService.getInstance())
} }
override val orderRepo: OrderRepository by lazy { override val orderRepo: OrderRepository by lazy {
OrderRepoImpl(AppDatabase.getInstance(context).orderDao()) OrderRepoImpl(AppDatabase.getInstance(context).orderDao())
@ -24,4 +33,10 @@ class AppDataContainer(private val context: Context) : AppContainer {
override val basketRepo: BasketRepository by lazy { override val basketRepo: BasketRepository by lazy {
BasketRepoImpl(AppDatabase.getInstance(context).basketDao()) BasketRepoImpl(AppDatabase.getInstance(context).basketDao())
} }
private val sneakerRepository: SneakerRepoImpl by lazy {
SneakerRepoImpl(AppDatabase.getInstance(context).sneakerDao())
}
private val remoteKeyRepository: RemoteKeysRepositoryImpl by lazy {
RemoteKeysRepositoryImpl(AppDatabase.getInstance(context).remoteKeysDao())
}
} }

View File

@ -0,0 +1,60 @@
package com.example.android_programming.api
import com.example.android_programming.api.model.SneakerRemote
import com.example.android_programming.api.model.UserRemote
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.Path
import retrofit2.http.Query
interface BackendService {
//SNEAKER
@GET("sneaker/get/{id}")
suspend fun getSneaker(
@Path("id") id: Int,
): SneakerRemote
@GET("sneaker/getAll")
suspend fun getSneakers(
@Query("page") page: Int,
@Query("size") size: Int,
): List<SneakerRemote>
//USER
@POST("user/signup")
suspend fun SignUp(
@Body user: UserRemote,
): UserRemote
companion object {
private const val BASE_URL = "https://59k4pfj3-8080.euw.devtunnels.ms/api/"
@Volatile
private var INSTANCE: BackendService? = null
fun getInstance(): BackendService {
return INSTANCE ?: synchronized(this) {
val logger = HttpLoggingInterceptor()
logger.level = HttpLoggingInterceptor.Level.BASIC
val client = OkHttpClient.Builder()
.addInterceptor(logger)
.build()
return Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(Json.asConverterFactory("application/json".toMediaType()))
.build()
.create(BackendService::class.java)
.also { INSTANCE = it }
}
}
}
}

View File

@ -0,0 +1,106 @@
package com.example.android_programming.api
import androidx.paging.ExperimentalPagingApi
import androidx.paging.LoadType
import androidx.paging.PagingState
import androidx.paging.RemoteMediator
import androidx.room.withTransaction
import com.example.android_programming.api.model.toSneaker
import com.example.android_programming.api.repository.RestSneakerRepository
import com.example.android_programming.database.AppDatabase
import com.example.android_programming.database.remotekeys.model.RemoteKeyType
import com.example.android_programming.database.remotekeys.model.RemoteKeys
import com.example.android_programming.database.remotekeys.repository.RemoteKeyRepository
import com.example.android_programming.database.remotekeys.repository.RemoteKeysRepositoryImpl
import com.example.android_programming.model.Sneaker
import com.example.android_programming.repository.SneakerRepoImpl
import com.example.android_programming.repository.SneakerRepository
import retrofit2.HttpException
import java.io.IOException
@OptIn(ExperimentalPagingApi::class)
class SneakerRemoteMediator(
private val service: BackendService,
private val sneakerRepository: SneakerRepoImpl,
private val database: AppDatabase,
private val dbRemoteKeyRepository:RemoteKeysRepositoryImpl
) : RemoteMediator<Int, Sneaker>() {
override suspend fun initialize(): InitializeAction {
return InitializeAction.LAUNCH_INITIAL_REFRESH
}
override suspend fun load(
loadType: LoadType,
state: PagingState<Int, Sneaker>
): MediatorResult {
val page = when (loadType) {
LoadType.REFRESH -> {
val remoteKeys = getRemoteKeyClosestToCurrentPosition(state)
remoteKeys?.nextKey?.minus(1) ?: 1
}
LoadType.PREPEND -> {
val remoteKeys = getRemoteKeyForFirstItem(state)
remoteKeys?.prevKey
?: return MediatorResult.Success(endOfPaginationReached = remoteKeys != null)
}
LoadType.APPEND -> {
val remoteKeys = getRemoteKeyForLastItem(state)
remoteKeys?.nextKey
?: return MediatorResult.Success(endOfPaginationReached = remoteKeys != null)
}
}
try {
val sneakers = service.getSneakers(page, state.config.pageSize).map { it.toSneaker() }
val endOfPaginationReached = sneakers.isEmpty()
database.withTransaction {
if (loadType == LoadType.REFRESH) {
dbRemoteKeyRepository.deleteRemoteKey(RemoteKeyType.SNEAKER)
sneakerRepository.clearSneakers()
}
val prevKey = if (page == 1) null else page - 1
val nextKey = if (endOfPaginationReached) null else page + 1
val keys = sneakers.map {
RemoteKeys(
entityId = it.sneakerId!!,
type = RemoteKeyType.SNEAKER,
prevKey = prevKey,
nextKey = nextKey
)
}
dbRemoteKeyRepository.createRemoteKeys(keys)
sneakerRepository.insertSneakers(sneakers)
}
return MediatorResult.Success(endOfPaginationReached = endOfPaginationReached)
} catch (exception: IOException) {
return MediatorResult.Error(exception)
} catch (exception: HttpException) {
return MediatorResult.Error(exception)
}
}
private suspend fun getRemoteKeyForLastItem(state: PagingState<Int, Sneaker>): RemoteKeys? {
return state.pages.lastOrNull { it.data.isNotEmpty() }?.data?.lastOrNull()
?.let { sneaker ->
sneaker.sneakerId?.let { dbRemoteKeyRepository.getAllRemoteKeys(it, RemoteKeyType.SNEAKER) }
}
}
private suspend fun getRemoteKeyForFirstItem(state: PagingState<Int, Sneaker>): RemoteKeys? {
return state.pages.firstOrNull { it.data.isNotEmpty() }?.data?.firstOrNull()
?.let { sneaker ->
sneaker.sneakerId?.let { dbRemoteKeyRepository.getAllRemoteKeys(it, RemoteKeyType.SNEAKER) }
}
}
private suspend fun getRemoteKeyClosestToCurrentPosition(
state: PagingState<Int, Sneaker>
): RemoteKeys? {
return state.anchorPosition?.let { position ->
state.closestItemToPosition(position)?.sneakerId?.let { sneakerUid ->
dbRemoteKeyRepository.getAllRemoteKeys(sneakerUid, RemoteKeyType.SNEAKER)
}
}
}
}

View File

@ -0,0 +1,32 @@
package com.example.android_programming.api.model
import com.example.android_programming.model.Sneaker
import kotlinx.serialization.Serializable
@Serializable
data class SneakerRemote (
val id: Int? = 0,
val brand: String = "",
val model: String = "",
val description: String = "",
val price: Double = 0.0,
val photo: Int = 0
)
fun SneakerRemote.toSneaker():Sneaker = Sneaker(
id,
brand,
model,
description,
price,
photo
)
fun Sneaker.toSneakerRemote():SneakerRemote = SneakerRemote(
sneakerId,
brand,
model,
description,
price,
photo
)

View File

@ -0,0 +1,39 @@
package com.example.android_programming.api.model
import androidx.room.ColumnInfo
import androidx.room.PrimaryKey
import com.example.android_programming.model.RoleEnum
import com.example.android_programming.model.Sneaker
import com.example.android_programming.model.User
import kotlinx.serialization.Serializable
@Serializable
data class UserRemote (
val id: Int? = 0,
val name: String = "",
val surname: String = "",
val email: String = "",
val password: String = "",
val role: RoleEnum = RoleEnum.User,
val photo: Int? = 0,
)
fun UserRemote.toUser(): User = User(
id,
name,
surname,
email,
password,
role,
photo
)
fun User.toUserRemote():UserRemote = UserRemote(
userId,
name,
surname,
email,
password,
role,
photo
)

View File

@ -0,0 +1,59 @@
package com.example.android_programming.api.repository
import android.util.Log
import androidx.paging.ExperimentalPagingApi
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.PagingSource
import com.example.android_programming.AppContainer
import com.example.android_programming.api.BackendService
import com.example.android_programming.api.SneakerRemoteMediator
import com.example.android_programming.api.model.toSneaker
import com.example.android_programming.database.AppDatabase
import com.example.android_programming.database.remotekeys.repository.RemoteKeysRepositoryImpl
import com.example.android_programming.model.Sneaker
import com.example.android_programming.repository.SneakerRepoImpl
import com.example.android_programming.repository.SneakerRepository
import kotlinx.coroutines.flow.Flow
class RestSneakerRepository(
private val service: BackendService,
private val dbSneakerRepository: SneakerRepoImpl,
private val database: AppDatabase,
private val dbRemoteKeyRepository: RemoteKeysRepositoryImpl
) : SneakerRepository {
override fun getAllSneakers(): Flow<PagingData<Sneaker>> {
val pagingSourceFactory = { dbSneakerRepository.getAllSneakersPagingSource() }
@OptIn(ExperimentalPagingApi::class)
return Pager(
config = PagingConfig(
pageSize = AppContainer.LIMIT,
enablePlaceholders = false
),
remoteMediator = SneakerRemoteMediator(
service,
dbSneakerRepository,
database,
dbRemoteKeyRepository,
),
pagingSourceFactory = pagingSourceFactory
).flow
}
override suspend fun getSneakerById(id: Int): Sneaker = service.getSneaker(id).toSneaker()
override suspend fun insertSneaker(sneaker: Sneaker) {
print("sdfsd")
}
override suspend fun updateSneaker(sneaker: Sneaker) {
print("sdfsd")
}
override suspend fun deleteSneaker(sneaker: Sneaker) {
print("sdfsd")
}
}

View File

@ -0,0 +1,24 @@
package com.example.android_programming.api.repository
import com.example.android_programming.api.BackendService
import com.example.android_programming.api.model.toUserRemote
import com.example.android_programming.model.User
import com.example.android_programming.repository.UserRepository
class RestUserRepository(
private var service: BackendService
): UserRepository {
override suspend fun createUser(user: User) {
val user1 = user.toUserRemote()
service.SignUp(user1)
}
override suspend fun updateUser(user: User) {
println()
}
override suspend fun deleteUser(user: User) {
println()
}
}

View File

@ -36,7 +36,7 @@ import kotlinx.coroutines.delay
@Composable @Composable
fun ChangePanel(navHostController: NavHostController, sneakerViewModel: SneakerViewModel = viewModel(factory = AppViewModelProvider.Factory)) { fun ChangePanel(navHostController: NavHostController, sneakerViewModel: SneakerViewModel = viewModel(factory = AppViewModelProvider.Factory)) {
val list = sneakerViewModel.sneakerList.collectAsLazyPagingItems() // val list = sneakerViewModel.sneakerList.collectAsLazyPagingItems()
Column( Column(
modifier = Modifier modifier = Modifier
@ -44,18 +44,18 @@ fun ChangePanel(navHostController: NavHostController, sneakerViewModel: SneakerV
.background(Color.White) .background(Color.White)
.padding(16.dp, 80.dp) .padding(16.dp, 80.dp)
) { ) {
Row { // Row {
LazyColumn( // LazyColumn(
modifier = Modifier // modifier = Modifier
.fillMaxSize() // .fillMaxSize()
) { // ) {
items(list.itemCount) { index -> // items(list.itemCount) { index ->
list[index]?.let { sneaker -> // list[index]?.let { sneaker ->
CardSneakerForChange(item = sneaker, navController = navHostController) // CardSneakerForChange(item = sneaker, navController = navHostController)
} // }
} // }
} // }
} // }
} }
} }

View File

@ -5,17 +5,28 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.material.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import androidx.paging.compose.collectAsLazyPagingItems import androidx.paging.compose.collectAsLazyPagingItems
import androidx.paging.compose.itemKey import androidx.paging.compose.itemKey
import com.example.android_programming.R
import com.example.android_programming.model.Sneaker import com.example.android_programming.model.Sneaker
import com.example.android_programming.vmodel.AppViewModelProvider import com.example.android_programming.vmodel.AppViewModelProvider
import com.example.android_programming.vmodel.OrderViewModel import com.example.android_programming.vmodel.OrderViewModel
import com.example.android_programming.vmodel.SneakerViewModel import com.example.android_programming.vmodel.SneakerViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.serialization.builtins.serializer
@Composable @Composable
fun RecyclerView(navHostController: NavHostController, sneakerViewModel: SneakerViewModel = viewModel(factory = AppViewModelProvider.Factory)) { fun RecyclerView(navHostController: NavHostController, sneakerViewModel: SneakerViewModel = viewModel(factory = AppViewModelProvider.Factory)) {

View File

@ -12,7 +12,7 @@ import kotlinx.coroutines.flow.Flow
@Dao @Dao
interface SneakerDao { interface SneakerDao {
@Insert @Insert
suspend fun insert(sneaker: Sneaker) suspend fun insert(vararg sneaker: Sneaker)
@Update @Update
suspend fun update(sneaker: Sneaker) suspend fun update(sneaker: Sneaker)
@ -22,7 +22,10 @@ interface SneakerDao {
@Query("SELECT*FROM Sneaker") @Query("SELECT*FROM Sneaker")
fun getAllSneakersPaged(): PagingSource<Int, Sneaker> fun getAllSneakersPaged(): PagingSource<Int, Sneaker>
@Query("select * from Sneaker")
fun getAll(): PagingSource<Int, Sneaker>
@Query("SELECT * FROM Sneaker WHERE sneakerId = :id") @Query("SELECT * FROM Sneaker WHERE sneakerId = :id")
suspend fun getSneakerById(id: Int): Sneaker suspend fun getSneakerById(id: Int): Sneaker
@Query("DELETE FROM Sneaker")
suspend fun deleteAll()
} }

View File

@ -10,6 +10,8 @@ import com.example.android_programming.dao.BasketDao
import com.example.android_programming.dao.OrderDao import com.example.android_programming.dao.OrderDao
import com.example.android_programming.dao.SneakerDao import com.example.android_programming.dao.SneakerDao
import com.example.android_programming.dao.UserDao import com.example.android_programming.dao.UserDao
import com.example.android_programming.database.remotekeys.dao.RemoteKeysDao
import com.example.android_programming.database.remotekeys.model.RemoteKeys
import com.example.android_programming.model.Basket import com.example.android_programming.model.Basket
import com.example.android_programming.model.BasketSneakers import com.example.android_programming.model.BasketSneakers
import com.example.android_programming.model.Order import com.example.android_programming.model.Order
@ -21,12 +23,13 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@Database(entities = [Sneaker::class, User::class, Order::class, OrderSneaker::class, Basket::class, BasketSneakers::class], version = 6) @Database(entities = [Sneaker::class, User::class, Order::class, OrderSneaker::class, Basket::class, BasketSneakers::class, RemoteKeys::class], version = 7)
abstract class AppDatabase : RoomDatabase() { abstract class AppDatabase : RoomDatabase() {
abstract fun sneakerDao(): SneakerDao abstract fun sneakerDao(): SneakerDao
abstract fun userDao(): UserDao abstract fun userDao(): UserDao
abstract fun orderDao(): OrderDao abstract fun orderDao(): OrderDao
abstract fun basketDao(): BasketDao abstract fun basketDao(): BasketDao
abstract fun remoteKeysDao(): RemoteKeysDao
companion object { companion object {
private const val DB_NAME: String = "my-db" private const val DB_NAME: String = "my-db"

View File

@ -0,0 +1,18 @@
package com.example.android_programming.database.remotekeys.dao
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.example.android_programming.database.remotekeys.model.RemoteKeyType
import com.example.android_programming.database.remotekeys.model.RemoteKeys
@Dao
interface RemoteKeysDao {
@Query("SELECT * FROM remote_keys WHERE entityId = :entityId AND type = :type")
suspend fun getRemoteKeys(entityId: Int, type: RemoteKeyType): RemoteKeys?
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAll(remoteKey: List<RemoteKeys>)
@Query("DELETE FROM remote_keys WHERE type = :type")
suspend fun clearRemoteKeys(type: RemoteKeyType)
}

View File

@ -0,0 +1,23 @@
package com.example.android_programming.database.remotekeys.model
import androidx.room.Entity
import androidx.room.PrimaryKey
import androidx.room.TypeConverter
import androidx.room.TypeConverters
import com.example.android_programming.model.Sneaker
enum class RemoteKeyType(private val type: String) {
SNEAKER(Sneaker::class.simpleName ?: "Sneaker");
@TypeConverter
fun toRemoteKeyType(value: String) = RemoteKeyType.values().first { it.type == value }
@TypeConverter
fun fromRemoteKeyType(value: RemoteKeyType) = value.type
}
@Entity(tableName = "remote_keys")
data class RemoteKeys(
@PrimaryKey val entityId: Int,
@TypeConverters(RemoteKeyType::class)
val type: RemoteKeyType,
val prevKey: Int?,
val nextKey: Int?
)

View File

@ -0,0 +1,10 @@
package com.example.android_programming.database.remotekeys.repository
import com.example.android_programming.database.remotekeys.model.RemoteKeyType
import com.example.android_programming.database.remotekeys.model.RemoteKeys
interface RemoteKeyRepository {
suspend fun getAllRemoteKeys(id: Int, type: RemoteKeyType): RemoteKeys?
suspend fun createRemoteKeys(remoteKeys: List<RemoteKeys>)
suspend fun deleteRemoteKey(type: RemoteKeyType)
}

View File

@ -0,0 +1,16 @@
package com.example.android_programming.database.remotekeys.repository
import com.example.android_programming.database.remotekeys.dao.RemoteKeysDao
import com.example.android_programming.database.remotekeys.model.RemoteKeyType
import com.example.android_programming.database.remotekeys.model.RemoteKeys
class RemoteKeysRepositoryImpl(private val remoteKeysDao: RemoteKeysDao) : RemoteKeyRepository {
override suspend fun getAllRemoteKeys(id: Int, type: RemoteKeyType) =
remoteKeysDao.getRemoteKeys(id, type)
override suspend fun createRemoteKeys(remoteKeys: List<RemoteKeys>) =
remoteKeysDao.insertAll(remoteKeys)
override suspend fun deleteRemoteKey(type: RemoteKeyType) =
remoteKeysDao.clearRemoteKeys(type)
}

View File

@ -5,6 +5,7 @@ import androidx.paging.PagingConfig
import androidx.paging.PagingData import androidx.paging.PagingData
import androidx.paging.PagingSource import androidx.paging.PagingSource
import androidx.paging.cachedIn import androidx.paging.cachedIn
import com.example.android_programming.AppContainer
import com.example.android_programming.dao.SneakerDao import com.example.android_programming.dao.SneakerDao
import com.example.android_programming.model.Sneaker import com.example.android_programming.model.Sneaker
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@ -18,12 +19,25 @@ class SneakerRepoImpl(private val sneakerDao: SneakerDao) : SneakerRepository {
override suspend fun deleteSneaker(sneaker: Sneaker) = sneakerDao.delete(sneaker) override suspend fun deleteSneaker(sneaker: Sneaker) = sneakerDao.delete(sneaker)
override suspend fun getSneakerById(id: Int): Sneaker = sneakerDao.getSneakerById(id) override suspend fun getSneakerById(id: Int): Sneaker = sneakerDao.getSneakerById(id)
override fun getAllSneakersPaged(): PagingSource<Int, Sneaker> = sneakerDao.getAllSneakersPaged() override fun getAllSneakers(): Flow<PagingData<Sneaker>> = Pager(
override fun call(): Flow<PagingData<Sneaker>> { config = PagingConfig(
return Pager( pageSize = AppContainer.LIMIT,
PagingConfig(pageSize = 5) enablePlaceholders = false
) { ),
sneakerDao.getAllSneakersPaged() pagingSourceFactory = sneakerDao::getAll
}.flow ).flow
}
suspend fun clearSneakers() = sneakerDao.deleteAll()
suspend fun insertSneakers(sneakers: List<Sneaker>) =
sneakerDao.insert(*sneakers.toTypedArray())
fun getAllSneakersPagingSource(): PagingSource<Int, Sneaker> = sneakerDao.getAll()
// override fun getAllSneakersPaged(): PagingSource<Int, Sneaker> = sneakerDao.getAllSneakersPaged()
// override fun call(): Flow<PagingData<Sneaker>> {
// return Pager(
// PagingConfig(pageSize = 5)
// ) {
// sneakerDao.getAllSneakersPaged()
// }.flow
// }
} }

View File

@ -10,6 +10,5 @@ interface SneakerRepository {
suspend fun updateSneaker(sneaker: Sneaker) suspend fun updateSneaker(sneaker: Sneaker)
suspend fun deleteSneaker(sneaker: Sneaker) suspend fun deleteSneaker(sneaker: Sneaker)
suspend fun getSneakerById(id: Int): Sneaker suspend fun getSneakerById(id: Int): Sneaker
fun getAllSneakersPaged(): PagingSource<Int, Sneaker> fun getAllSneakers(): Flow<PagingData<Sneaker>>
fun call(): Flow<PagingData<Sneaker>>
} }

View File

@ -13,7 +13,7 @@ class UserRepoImpl(private val userDao: UserDao) : UserRepository {
override suspend fun deleteUser(user: User) = userDao.deleteUser(user) override suspend fun deleteUser(user: User) = userDao.deleteUser(user)
override suspend fun getUserById(id: Int): User = userDao.getUserById(id) // override suspend fun getUserById(id: Int): User = userDao.getUserById(id)
//
override suspend fun getUserByEmail(email: String): User = userDao.getUserByEmail(email) // override suspend fun getUserByEmail(email: String): User = userDao.getUserByEmail(email)
} }

View File

@ -9,6 +9,6 @@ interface UserRepository {
suspend fun createUser(user: User) suspend fun createUser(user: User)
suspend fun updateUser(user: User) suspend fun updateUser(user: User)
suspend fun deleteUser(user: User) suspend fun deleteUser(user: User)
suspend fun getUserById(id: Int): User // suspend fun getUserById(id: Int): User
suspend fun getUserByEmail(email: String): User // suspend fun getUserByEmail(email: String): User
} }

View File

@ -1,5 +1,7 @@
package com.example.android_programming.vmodel package com.example.android_programming.vmodel
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
@ -14,22 +16,27 @@ import androidx.paging.cachedIn
import androidx.paging.map import androidx.paging.map
import com.example.android_programming.App import com.example.android_programming.App
import com.example.android_programming.R import com.example.android_programming.R
import com.example.android_programming.api.model.toSneakerRemote
import com.example.android_programming.api.repository.RestSneakerRepository
import com.example.android_programming.database.AppDatabase import com.example.android_programming.database.AppDatabase
import com.example.android_programming.model.Sneaker import com.example.android_programming.model.Sneaker
import com.example.android_programming.repository.SneakerRepository import com.example.android_programming.repository.SneakerRepository
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class SneakerViewModel(private val sneakerRepository: SneakerRepository): ViewModel() { class SneakerViewModel(private val sneakerRepository: RestSneakerRepository): ViewModel() {
val sneakerList = sneakerRepository.getAllSneakers()
var brand = mutableStateOf("") var brand = mutableStateOf("")
val model = mutableStateOf("") val model = mutableStateOf("")
val description = mutableStateOf("") val description = mutableStateOf("")
val price = mutableStateOf("") val price = mutableStateOf("")
val photo = mutableIntStateOf(R.drawable.img) val photo = mutableIntStateOf(R.drawable.img)
val sneakerList = sneakerRepository.call().cachedIn(viewModelScope)
var sneaker: Sneaker? = null var sneaker: Sneaker? = null
private var _record = MutableStateFlow<Sneaker?>(null)
var record: StateFlow<Sneaker?> = _record
fun insertSneaker() = viewModelScope.launch { fun insertSneaker() = viewModelScope.launch {
val sneaker = Sneaker( val sneaker = Sneaker(
brand = brand.value, brand = brand.value,
@ -45,10 +52,6 @@ class SneakerViewModel(private val sneakerRepository: SneakerRepository): ViewMo
sneakerRepository.deleteSneaker(sneaker) sneakerRepository.deleteSneaker(sneaker)
} }
fun getSneakerById(id: Int) = viewModelScope.launch {
sneakerRepository.getSneakerById(id)
}
fun UpdateSneaker(sneaker: Sneaker) = viewModelScope.launch { fun UpdateSneaker(sneaker: Sneaker) = viewModelScope.launch {
sneakerRepository.updateSneaker(sneaker) sneakerRepository.updateSneaker(sneaker)
} }

View File

@ -7,6 +7,7 @@ import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.CreationExtras import androidx.lifecycle.viewmodel.CreationExtras
import com.example.android_programming.App import com.example.android_programming.App
import com.example.android_programming.GlobalUser import com.example.android_programming.GlobalUser
import com.example.android_programming.R
import com.example.android_programming.database.AppDatabase import com.example.android_programming.database.AppDatabase
import com.example.android_programming.model.Basket import com.example.android_programming.model.Basket
import com.example.android_programming.model.RoleEnum import com.example.android_programming.model.RoleEnum
@ -28,16 +29,17 @@ class UserViewModel(private val userRepository: UserRepository): ViewModel() {
surname = surname.value, surname = surname.value,
email = email.value, email = email.value,
password = password.value, password = password.value,
role = RoleEnum.User role = RoleEnum.User,
photo = R.drawable.shailushai
) )
userRepository.createUser(user) userRepository.createUser(user)
} }
fun authUser() = viewModelScope.launch { fun authUser() = viewModelScope.launch {
val user = userRepository.getUserByEmail(email.value) // val user = userRepository.getUserByEmail(email.value)
if (password.value != "" && user.password == password.value) { // if (password.value != "" && user.password == password.value) {
val globalUser = GlobalUser.getInstance() // val globalUser = GlobalUser.getInstance()
globalUser.setUser(user) // globalUser.setUser(user)
} // }
} }
fun isValidEmail(email: String): Boolean { fun isValidEmail(email: String): Boolean {