Skip to content

Commit

Permalink
Added pagination invalidation.
Browse files Browse the repository at this point in the history
  • Loading branch information
devandrepascoa committed May 31, 2024
1 parent 593f068 commit df11ee8
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ object ApplicationModule {
@Singleton
fun provideOkHttpClient(): OkHttpClient {
return OkHttpClient.Builder()
.connectTimeout(100, java.util.concurrent.TimeUnit.SECONDS)
.readTimeout(100, java.util.concurrent.TimeUnit.SECONDS)
.writeTimeout(100, java.util.concurrent.TimeUnit.SECONDS)
// .connectTimeout(100, java.util.concurrent.TimeUnit.SECONDS)
// .readTimeout(100, java.util.concurrent.TimeUnit.SECONDS)
// .writeTimeout(100, java.util.concurrent.TimeUnit.SECONDS)
//.connectionSpecs(listOf(okhttp3.ConnectionSpec.MODERN_TLS))
.build()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ interface PharmacyDao {
@Upsert
suspend fun upsertPharmacyMedicineList(pharmacyMedicineList: List<PharmacyMedicineEntity>)

@Upsert
suspend fun upsertPharmacyMedicine(pharmacyMedicine: PharmacyMedicineEntity)

@Upsert(entity = PharmacyMedicineEntity::class)
suspend fun upsertPharmacyMedicineNoStockList(
pharmacyMedicineNoStockList: List<PharmacyMedicineNoStockEntity>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@ import pt.ulisboa.ist.pharmacist.repository.local.medicines.MedicineDao
import pt.ulisboa.ist.pharmacist.repository.local.medicines.PharmacyMedicineEntity
import pt.ulisboa.ist.pharmacist.repository.local.medicines.PharmacyMedicineFlatEntity
import pt.ulisboa.ist.pharmacist.repository.network.connection.isSuccess
import pt.ulisboa.ist.pharmacist.service.real_time_updates.RealTimeUpdateSubscription
import pt.ulisboa.ist.pharmacist.service.real_time_updates.RealTimeUpdatesService

@OptIn(ExperimentalPagingApi::class)
class PharmacyMedicinesRemoteMediator(
private val pharmacistDb: PharmacistDatabase,
private val pharmacyApi: PharmacyApi,
private val pharmacyId: Long
private val pharmacyId: Long,
private val realTimeUpdatesService: RealTimeUpdatesService,
) : RemoteMediator<Int, PharmacyMedicineFlatEntity>() {

override suspend fun load(
Expand Down Expand Up @@ -66,13 +69,23 @@ class PharmacyMedicinesRemoteMediator(
boxPhotoUrl = it.medicine.boxPhotoUrl
)
})

pharmacistDb.pharmacyDao().upsertPharmacyMedicineList(result.data.medicines.map {
PharmacyMedicineEntity(
pharmacyId = pharmacyId,
medicineId = it.medicine.medicineId,
stock = it.stock
)
})

realTimeUpdatesService.subscribeToUpdates(
result.data.medicines.map {
RealTimeUpdateSubscription.pharmacyMedicineStock(
pharmacyId = pharmacyId,
medicineId = it.medicine.medicineId
)
}
)
}

Log.d(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class PharmacyActivity : PharmacistActivity() {

Log.d("PharmacyActivity", "Loading pharmacy")
viewModel.loadPharmacy(pharmacyId)
viewModel.triggerUpdateFlow.value = !viewModel.triggerUpdateFlow.value
viewModel.invalidate()
}

override fun onCreate(savedInstanceState: Bundle?) {
Expand Down Expand Up @@ -199,5 +199,11 @@ class PharmacyActivity : PharmacistActivity() {
putExtra(PHARMACY_ID, pharmacyId)
}
}

fun getNavigationIntent(applicationContext: Context, pharmacyId: Long): Intent {
return Intent(applicationContext, PharmacyActivity::class.java).apply {
putExtra(PHARMACY_ID, pharmacyId)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package pt.ulisboa.ist.pharmacist.ui.screens.pharmacy

import android.content.Context
import android.net.ConnectivityManager
import android.util.Log
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.graphics.ImageBitmap
import androidx.lifecycle.viewModelScope
import androidx.paging.ExperimentalPagingApi
import androidx.paging.InvalidatingPagingSourceFactory
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.cachedIn
Expand All @@ -19,13 +18,12 @@ import dagger.assisted.AssistedInject
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import pt.ulisboa.ist.pharmacist.domain.pharmacies.Pharmacy
import pt.ulisboa.ist.pharmacist.repository.local.PharmacistDatabase
import pt.ulisboa.ist.pharmacist.repository.local.medicines.PharmacyMedicineEntity
import pt.ulisboa.ist.pharmacist.repository.mappers.toMedicineEntity
import pt.ulisboa.ist.pharmacist.repository.mappers.toMedicineStock
import pt.ulisboa.ist.pharmacist.repository.mappers.toPharmacy
Expand Down Expand Up @@ -69,13 +67,6 @@ class PharmacyViewModel @AssistedInject constructor(
fun create(pharmacyId: Long): PharmacyViewModel
}

fun isNetworkAvailable(context: Context): Boolean {
val connectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
val activeNetworkInfo = connectivityManager?.activeNetworkInfo
return activeNetworkInfo != null && activeNetworkInfo.isConnected
}

var loadingState by mutableStateOf(NOT_LOADED)
private set

Expand All @@ -85,36 +76,35 @@ class PharmacyViewModel @AssistedInject constructor(
var pharmacyImage by mutableStateOf<ImageBitmap?>(null)
private set

val triggerUpdateFlow = MutableStateFlow(false)
private val invalidatingPagingSourceFactory = InvalidatingPagingSourceFactory {
pharmacistDb.pharmacyDao().pagingSourcePharmacyMedicineByPharmacyId(
pharmacyId = pharmacyId
)
}

@OptIn(ExperimentalPagingApi::class, ExperimentalCoroutinesApi::class)
val medicinePagingFlow =
triggerUpdateFlow.flatMapLatest {
Pager(
config = PagingConfig(
pageSize = PAGE_SIZE,
prefetchDistance = PREFETCH_DISTANCE,
enablePlaceholders = false,
initialLoadSize = PAGE_SIZE
),
remoteMediator = PharmacyMedicinesRemoteMediator(
pharmacistDb = pharmacistDb,
pharmacyApi = pharmacyApi,
pharmacyId = pharmacyId
),
pagingSourceFactory = {
pharmacistDb.pharmacyDao().pagingSourcePharmacyMedicineByPharmacyId(
pharmacyId = pharmacyId
)
}
)
.flow
.map { pagingData ->
pagingData.map { pharmacyMedicineFlatEntity ->
pharmacyMedicineFlatEntity.toMedicineStock()
}
Pager(
config = PagingConfig(
pageSize = PAGE_SIZE,
prefetchDistance = PREFETCH_DISTANCE,
enablePlaceholders = false,
initialLoadSize = PAGE_SIZE
),
remoteMediator = PharmacyMedicinesRemoteMediator(
pharmacistDb = pharmacistDb,
pharmacyApi = pharmacyApi,
pharmacyId = pharmacyId,
realTimeUpdatesService = realTimeUpdatesService
),
pagingSourceFactory = invalidatingPagingSourceFactory
)
.flow
.map { pagingData ->
pagingData.map { pharmacyMedicineFlatEntity ->
pharmacyMedicineFlatEntity.toMedicineStock()
}
}
}
.cachedIn(viewModelScope)

fun listenForRealTimeUpdates() = viewModelScope.launch {
Expand Down Expand Up @@ -161,7 +151,16 @@ class PharmacyViewModel @AssistedInject constructor(
"RealTimeUpdatesService",
"Received medicine stock update: $medicineStockData"
)
// triggerUpdateFlow.value = !triggerUpdateFlow.value
viewModelScope.launch {
pharmacistDb.pharmacyDao().upsertPharmacyMedicine(
PharmacyMedicineEntity(
pharmacyId = pharmacyId,
medicineId = medicineStockData.medicineId,
stock = medicineStockData.stock
)
)
invalidatingPagingSourceFactory.invalidate()
}
}
)
}
Expand All @@ -181,7 +180,7 @@ class PharmacyViewModel @AssistedInject constructor(
RealTimeUpdateSubscription.pharmacyUserRating(pharmacyId),
RealTimeUpdateSubscription.pharmacyGlobalRating(pharmacyId),
RealTimeUpdateSubscription.pharmacyUserFlagged(pharmacyId),
RealTimeUpdateSubscription.pharmacyUserFavorited(pharmacyId)
RealTimeUpdateSubscription.pharmacyUserFavorited(pharmacyId),
)
)
loadingState = LOADED
Expand Down Expand Up @@ -287,7 +286,6 @@ class PharmacyViewModel @AssistedInject constructor(
if (result != null && result.isSuccess()) {
Log.d("PharmacyViewModel", "Modified stock in API")
}
triggerUpdateFlow.value = !triggerUpdateFlow.value
}
}

Expand All @@ -303,7 +301,7 @@ class PharmacyViewModel @AssistedInject constructor(
if (result != null && result.isSuccess()) {
result as APIResult.Success
pharmacistDb.medicineDao().upsertMedicine(result.data.toMedicineEntity())
triggerUpdateFlow.value = !triggerUpdateFlow.value
invalidatingPagingSourceFactory.invalidate()

realTimeUpdatesService.subscribeToUpdates(
listOf(
Expand All @@ -330,6 +328,10 @@ class PharmacyViewModel @AssistedInject constructor(
}
}

fun invalidate() {
invalidatingPagingSourceFactory.invalidate()
}

enum class PharmacyLoadingState {
NOT_LOADED,
LOADING,
Expand Down

0 comments on commit df11ee8

Please sign in to comment.