Lab 05: add performances rest
This commit is contained in:
parent
2c5adc70ed
commit
ca9a734bf3
@ -28,7 +28,7 @@ interface MyServerService {
|
|||||||
suspend fun getPerformances(
|
suspend fun getPerformances(
|
||||||
@Query("_page") page: Int,
|
@Query("_page") page: Int,
|
||||||
@Query("_limit") limit: Int,
|
@Query("_limit") limit: Int,
|
||||||
): List<PersonRemote>
|
): List<PerformanceRemote>
|
||||||
|
|
||||||
@GET("events")
|
@GET("events")
|
||||||
suspend fun getEvents(
|
suspend fun getEvents(
|
||||||
@ -41,6 +41,11 @@ interface MyServerService {
|
|||||||
@Path("id") id: Int,
|
@Path("id") id: Int,
|
||||||
): PerformanceRemote
|
): PerformanceRemote
|
||||||
|
|
||||||
|
@GET("persons/{id}")
|
||||||
|
suspend fun getPerson(
|
||||||
|
@Path("id") id: Int,
|
||||||
|
): PersonRemote
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val BASE_URL = "http://10.0.2.2:26000/"
|
private const val BASE_URL = "http://10.0.2.2:26000/"
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package com.example.mobile_labs.api.models
|
package com.example.mobile_labs.api.models
|
||||||
|
|
||||||
|
import com.example.mobile_labs.api.MyServerService
|
||||||
import com.example.mobile_labs.database.performance.model.Performance
|
import com.example.mobile_labs.database.performance.model.Performance
|
||||||
|
import com.example.mobile_labs.database.performance.model.PerformanceWithPeople
|
||||||
import com.example.mobile_labs.database.person.model.Person
|
import com.example.mobile_labs.database.person.model.Person
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@ -12,7 +14,8 @@ data class PerformanceRemote(
|
|||||||
val authorId: Int = 0,
|
val authorId: Int = 0,
|
||||||
val directorId: Int = 0,
|
val directorId: Int = 0,
|
||||||
val imageURL: String = "",
|
val imageURL: String = "",
|
||||||
val previewImageURL: String = ""
|
val previewImageURL: String = "",
|
||||||
|
val actors: List<Int> = listOf()
|
||||||
)
|
)
|
||||||
|
|
||||||
fun PerformanceRemote.toPerformance(): Performance = Performance(
|
fun PerformanceRemote.toPerformance(): Performance = Performance(
|
||||||
@ -24,3 +27,17 @@ fun PerformanceRemote.toPerformance(): Performance = Performance(
|
|||||||
imageURL,
|
imageURL,
|
||||||
previewImageURL
|
previewImageURL
|
||||||
)
|
)
|
||||||
|
|
||||||
|
suspend fun PerformanceRemote.toPerformanceWithPeople(service: MyServerService): PerformanceWithPeople {
|
||||||
|
val actorsList = ArrayList<Person>();
|
||||||
|
actors.forEach {id ->
|
||||||
|
actorsList.add(service.getPerson(id).toPerson())
|
||||||
|
}
|
||||||
|
|
||||||
|
return PerformanceWithPeople(
|
||||||
|
service.getPerformance(id).toPerformance(),
|
||||||
|
service.getPerson(authorId).toPerson(),
|
||||||
|
service.getPerson(directorId).toPerson(),
|
||||||
|
actorsList.toList()
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,112 @@
|
|||||||
|
package com.example.mobile_labs.api.performance
|
||||||
|
|
||||||
|
import androidx.paging.ExperimentalPagingApi
|
||||||
|
import androidx.paging.LoadType
|
||||||
|
import androidx.paging.PagingState
|
||||||
|
import androidx.paging.RemoteMediator
|
||||||
|
import androidx.room.withTransaction
|
||||||
|
import com.example.mobile_labs.api.MyServerService
|
||||||
|
import com.example.mobile_labs.api.models.toPerformance
|
||||||
|
import com.example.mobile_labs.api.models.toPerson
|
||||||
|
import com.example.mobile_labs.api.people.RestPersonRepository
|
||||||
|
import com.example.mobile_labs.database.AppDatabase
|
||||||
|
import com.example.mobile_labs.database.performance.model.Performance
|
||||||
|
import com.example.mobile_labs.database.performance.repository.OfflinePerformanceRepository
|
||||||
|
import com.example.mobile_labs.database.person.repository.OfflinePersonRepository
|
||||||
|
import com.example.mobile_labs.database.remotekeys.model.RemoteKeyType
|
||||||
|
import com.example.mobile_labs.database.remotekeys.model.RemoteKeys
|
||||||
|
import com.example.mobile_labs.database.remotekeys.repository.OfflineRemoteKeyRepository
|
||||||
|
import retrofit2.HttpException
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
@OptIn(ExperimentalPagingApi::class)
|
||||||
|
class PerformanceRemoteMediator(
|
||||||
|
private val service: MyServerService,
|
||||||
|
private val dbPerformanceRepository: OfflinePerformanceRepository,
|
||||||
|
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
|
||||||
|
private val personRestRepository: RestPersonRepository,
|
||||||
|
private val database: AppDatabase
|
||||||
|
) : RemoteMediator<Int, Performance>() {
|
||||||
|
|
||||||
|
override suspend fun initialize(): InitializeAction {
|
||||||
|
return InitializeAction.LAUNCH_INITIAL_REFRESH
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun load(
|
||||||
|
loadType: LoadType,
|
||||||
|
state: PagingState<Int, Performance>
|
||||||
|
): 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 performances = service.getPerformances(page, state.config.pageSize).map { it.toPerformance() }
|
||||||
|
val endOfPaginationReached = performances.isEmpty()
|
||||||
|
database.withTransaction {
|
||||||
|
if (loadType == LoadType.REFRESH) {
|
||||||
|
dbRemoteKeyRepository.deleteRemoteKey(RemoteKeyType.PERSON)
|
||||||
|
dbPerformanceRepository.clearPerformances()
|
||||||
|
}
|
||||||
|
val prevKey = if (page == 1) null else page - 1
|
||||||
|
val nextKey = if (endOfPaginationReached) null else page + 1
|
||||||
|
val keys = performances.map {
|
||||||
|
RemoteKeys(
|
||||||
|
entityId = it.performance_uid !!,
|
||||||
|
type = RemoteKeyType.PERSON,
|
||||||
|
prevKey = prevKey,
|
||||||
|
nextKey = nextKey
|
||||||
|
)
|
||||||
|
}
|
||||||
|
personRestRepository.getAllPeople()
|
||||||
|
dbRemoteKeyRepository.createRemoteKeys(keys)
|
||||||
|
dbPerformanceRepository.insertPerformances(performances)
|
||||||
|
}
|
||||||
|
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, Performance>): RemoteKeys? {
|
||||||
|
return state.pages.lastOrNull { it.data.isNotEmpty() }?.data?.lastOrNull()
|
||||||
|
?.let { performance ->
|
||||||
|
dbRemoteKeyRepository.getAllRemoteKeys(performance.performance_uid !!, RemoteKeyType.PERSON)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun getRemoteKeyForFirstItem(state: PagingState<Int, Performance>): RemoteKeys? {
|
||||||
|
return state.pages.firstOrNull { it.data.isNotEmpty() }?.data?.firstOrNull()
|
||||||
|
?.let { performance ->
|
||||||
|
dbRemoteKeyRepository.getAllRemoteKeys(performance.performance_uid !!, RemoteKeyType.PERSON)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun getRemoteKeyClosestToCurrentPosition(
|
||||||
|
state: PagingState<Int, Performance>
|
||||||
|
): RemoteKeys? {
|
||||||
|
return state.anchorPosition?.let { position ->
|
||||||
|
state.closestItemToPosition(position)?.performance_uid?.let { performanceUid ->
|
||||||
|
dbRemoteKeyRepository.getAllRemoteKeys(performanceUid, RemoteKeyType.PERSON)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package com.example.mobile_labs.api.performance
|
||||||
|
|
||||||
|
import androidx.paging.ExperimentalPagingApi
|
||||||
|
import androidx.paging.Pager
|
||||||
|
import androidx.paging.PagingConfig
|
||||||
|
import androidx.paging.PagingData
|
||||||
|
import com.example.mobile_labs.api.MyServerService
|
||||||
|
import com.example.mobile_labs.api.models.toPerformance
|
||||||
|
import com.example.mobile_labs.api.models.toPerformanceWithPeople
|
||||||
|
import com.example.mobile_labs.api.people.RestPersonRepository
|
||||||
|
import com.example.mobile_labs.common.AppDataContainer
|
||||||
|
import com.example.mobile_labs.common.PerformanceRepository
|
||||||
|
import com.example.mobile_labs.common.PersonRepository
|
||||||
|
import com.example.mobile_labs.database.AppDatabase
|
||||||
|
import com.example.mobile_labs.database.performance.model.Performance
|
||||||
|
import com.example.mobile_labs.database.performance.model.PerformanceWithPeople
|
||||||
|
import com.example.mobile_labs.database.performance.repository.OfflinePerformanceRepository
|
||||||
|
import com.example.mobile_labs.database.person.model.Person
|
||||||
|
import com.example.mobile_labs.database.person.repository.OfflinePersonRepository
|
||||||
|
import com.example.mobile_labs.database.remotekeys.repository.OfflineRemoteKeyRepository
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
class RestPerformanceRepository(
|
||||||
|
private val service: MyServerService,
|
||||||
|
private val dbPerformanceRepository: OfflinePerformanceRepository,
|
||||||
|
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
|
||||||
|
private val personRestRepository: RestPersonRepository,
|
||||||
|
private val database: AppDatabase
|
||||||
|
) : PerformanceRepository {
|
||||||
|
override fun getAllPerformances(): Flow<PagingData<Performance>> {
|
||||||
|
|
||||||
|
val pagingSourceFactory = { dbPerformanceRepository.getAllPerformancesPagingSource() }
|
||||||
|
|
||||||
|
@OptIn(ExperimentalPagingApi::class)
|
||||||
|
return Pager(
|
||||||
|
config = PagingConfig(
|
||||||
|
pageSize = AppDataContainer.LIMIT,
|
||||||
|
enablePlaceholders = false
|
||||||
|
),
|
||||||
|
remoteMediator = PerformanceRemoteMediator(
|
||||||
|
service,
|
||||||
|
dbPerformanceRepository,
|
||||||
|
dbRemoteKeyRepository,
|
||||||
|
personRestRepository,
|
||||||
|
database,
|
||||||
|
),
|
||||||
|
pagingSourceFactory = pagingSourceFactory
|
||||||
|
).flow
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getPerformance(uid: Int): PerformanceWithPeople =
|
||||||
|
service.getPerformance(uid).toPerformanceWithPeople(service)
|
||||||
|
}
|
@ -3,6 +3,7 @@ package com.example.mobile_labs.common
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.example.mobile_labs.api.MyServerService
|
import com.example.mobile_labs.api.MyServerService
|
||||||
import com.example.mobile_labs.api.people.RestPersonRepository
|
import com.example.mobile_labs.api.people.RestPersonRepository
|
||||||
|
import com.example.mobile_labs.api.performance.RestPerformanceRepository
|
||||||
import com.example.mobile_labs.database.event.repository.EventRepository
|
import com.example.mobile_labs.database.event.repository.EventRepository
|
||||||
import com.example.mobile_labs.database.event.repository.OfflineEventRepository
|
import com.example.mobile_labs.database.event.repository.OfflineEventRepository
|
||||||
import com.example.mobile_labs.database.performance.repository.OfflinePerformanceRepository
|
import com.example.mobile_labs.database.performance.repository.OfflinePerformanceRepository
|
||||||
@ -14,7 +15,7 @@ import com.example.mobile_labs.database.remotekeys.repository.RemoteKeyRepositor
|
|||||||
interface AppContainer {
|
interface AppContainer {
|
||||||
val personRestRepository: RestPersonRepository
|
val personRestRepository: RestPersonRepository
|
||||||
val eventRepository: EventRepository
|
val eventRepository: EventRepository
|
||||||
val performanceRepository: PerformanceRepository
|
val performanceRestRepository: RestPerformanceRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
class AppDataContainer(private val context: Context) : AppContainer {
|
class AppDataContainer(private val context: Context) : AppContainer {
|
||||||
@ -22,7 +23,7 @@ class AppDataContainer(private val context: Context) : AppContainer {
|
|||||||
OfflineEventRepository(AppDatabase.getInstance(context).eventDao())
|
OfflineEventRepository(AppDatabase.getInstance(context).eventDao())
|
||||||
}
|
}
|
||||||
|
|
||||||
override val performanceRepository: PerformanceRepository by lazy {
|
val performanceRepository: OfflinePerformanceRepository by lazy {
|
||||||
OfflinePerformanceRepository(AppDatabase.getInstance(context).performanceDao())
|
OfflinePerformanceRepository(AppDatabase.getInstance(context).performanceDao())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,6 +43,16 @@ class AppDataContainer(private val context: Context) : AppContainer {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val performanceRestRepository: RestPerformanceRepository by lazy {
|
||||||
|
RestPerformanceRepository(
|
||||||
|
MyServerService.getInstance(),
|
||||||
|
performanceRepository,
|
||||||
|
remoteKeyRepository,
|
||||||
|
personRestRepository,
|
||||||
|
AppDatabase.getInstance(context)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TIMEOUT = 5000L
|
const val TIMEOUT = 5000L
|
||||||
const val LIMIT = 3
|
const val LIMIT = 3
|
||||||
|
@ -20,10 +20,10 @@ object AppViewModelProvider {
|
|||||||
EventListViewModel(theatreApplication().container.eventRepository)
|
EventListViewModel(theatreApplication().container.eventRepository)
|
||||||
}
|
}
|
||||||
initializer {
|
initializer {
|
||||||
PerformanceListViewModel(theatreApplication().container.performanceRepository)
|
PerformanceListViewModel(theatreApplication().container.performanceRestRepository)
|
||||||
}
|
}
|
||||||
initializer {
|
initializer {
|
||||||
PerformanceViewModel(this.createSavedStateHandle(), theatreApplication().container.performanceRepository)
|
PerformanceViewModel(this.createSavedStateHandle(), theatreApplication().container.performanceRestRepository)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,5 @@ import kotlinx.coroutines.flow.Flow
|
|||||||
|
|
||||||
interface PerformanceRepository {
|
interface PerformanceRepository {
|
||||||
fun getAllPerformances(): Flow<PagingData<Performance>>
|
fun getAllPerformances(): Flow<PagingData<Performance>>
|
||||||
fun getPerformance(uid: Int): Flow<PerformanceWithPeople?>
|
suspend fun getPerformance(uid: Int): PerformanceWithPeople
|
||||||
suspend fun insertPerformance(performance: Performance)
|
|
||||||
suspend fun updatePerformance(performance: Performance)
|
|
||||||
suspend fun deletePerformance(performance: Performance)
|
|
||||||
}
|
}
|
@ -20,11 +20,14 @@ interface PerformanceDao {
|
|||||||
fun getByUid(uid: Int): Flow<PerformanceWithPeople>
|
fun getByUid(uid: Int): Flow<PerformanceWithPeople>
|
||||||
|
|
||||||
@Insert
|
@Insert
|
||||||
suspend fun insert(performance: Performance)
|
suspend fun insert(vararg performance: Performance)
|
||||||
|
|
||||||
@Update
|
@Update
|
||||||
suspend fun update(performance: Performance)
|
suspend fun update(performance: Performance)
|
||||||
|
|
||||||
@Delete
|
@Delete
|
||||||
suspend fun delete(performance: Performance)
|
suspend fun delete(performance: Performance)
|
||||||
|
|
||||||
|
@Query("DELETE FROM performances")
|
||||||
|
suspend fun deleteAll()
|
||||||
}
|
}
|
@ -3,12 +3,15 @@ package com.example.mobile_labs.database.performance.repository
|
|||||||
import androidx.paging.Pager
|
import androidx.paging.Pager
|
||||||
import androidx.paging.PagingConfig
|
import androidx.paging.PagingConfig
|
||||||
import androidx.paging.PagingData
|
import androidx.paging.PagingData
|
||||||
|
import androidx.paging.PagingSource
|
||||||
import com.example.mobile_labs.common.PerformanceRepository
|
import com.example.mobile_labs.common.PerformanceRepository
|
||||||
import com.example.mobile_labs.common.AppDataContainer
|
import com.example.mobile_labs.common.AppDataContainer
|
||||||
import com.example.mobile_labs.database.performance.dao.PerformanceDao
|
import com.example.mobile_labs.database.performance.dao.PerformanceDao
|
||||||
import com.example.mobile_labs.database.performance.model.Performance
|
import com.example.mobile_labs.database.performance.model.Performance
|
||||||
import com.example.mobile_labs.database.performance.model.PerformanceWithPeople
|
import com.example.mobile_labs.database.performance.model.PerformanceWithPeople
|
||||||
|
import com.example.mobile_labs.database.person.model.Person
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
|
|
||||||
class OfflinePerformanceRepository(private val performanceDao: PerformanceDao) :
|
class OfflinePerformanceRepository(private val performanceDao: PerformanceDao) :
|
||||||
PerformanceRepository {
|
PerformanceRepository {
|
||||||
@ -19,11 +22,18 @@ class OfflinePerformanceRepository(private val performanceDao: PerformanceDao) :
|
|||||||
),
|
),
|
||||||
pagingSourceFactory = performanceDao::getAll
|
pagingSourceFactory = performanceDao::getAll
|
||||||
).flow
|
).flow
|
||||||
override fun getPerformance(uid: Int): Flow<PerformanceWithPeople?> = performanceDao.getByUid(uid);
|
override suspend fun getPerformance(uid: Int): PerformanceWithPeople = performanceDao.getByUid(uid).first();
|
||||||
|
|
||||||
override suspend fun insertPerformance(performance: Performance) = performanceDao.insert(performance);
|
suspend fun insertPerformance(performance: Performance) = performanceDao.insert(performance);
|
||||||
|
|
||||||
override suspend fun updatePerformance(performance: Performance) = performanceDao.update(performance);
|
suspend fun updatePerformance(performance: Performance) = performanceDao.update(performance);
|
||||||
|
|
||||||
override suspend fun deletePerformance(performance: Performance) = performanceDao.delete(performance);
|
suspend fun deletePerformance(performance: Performance) = performanceDao.delete(performance);
|
||||||
|
|
||||||
|
suspend fun clearPerformances() = performanceDao.deleteAll()
|
||||||
|
|
||||||
|
suspend fun insertPerformances(performances: List<Performance>) =
|
||||||
|
performanceDao.insert(*performances.toTypedArray())
|
||||||
|
|
||||||
|
fun getAllPerformancesPagingSource(): PagingSource<Int, Performance> = performanceDao.getAll()
|
||||||
}
|
}
|
@ -26,8 +26,6 @@ class PerformanceViewModel(
|
|||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
if (studentUid > 0) {
|
if (studentUid > 0) {
|
||||||
performanceUiState = performanceRepository.getPerformance(studentUid)
|
performanceUiState = performanceRepository.getPerformance(studentUid)
|
||||||
.filterNotNull()
|
|
||||||
.first()
|
|
||||||
.toUiState()
|
.toUiState()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user