在我的 Android 应用中,我从房间数据库获取数据并将其显示在 UI 上。我正在缓存映射数据。这是在视图模型中缓存数据的正确方法吗?我是 Android 新手,如果我错了,请纠正我。我正在使用 withContext 切换调度程序,我们需要切换吗?
@HiltViewModel
class TrainVM @Inject constructor(
private val repo: Repository, // Inject the repository
private val apiRepo: KtorRepo
) : ViewModel() {
private var localSchCache = mutableMapOf<String, TrainSchStat>()
private var trainSchCache = mutableMapOf<String, TrainWithNew>()
private val _trainStatus =
MutableStateFlow<ViewState<TrainWithNew>>(value = ViewState.Loading)
val trainStatus = _trainStatus.asStateFlow()
private val _isLoading = MutableStateFlow(true)
val isLoading = _isLoading.asStateFlow()
fun fetchTrain(train: String, isLive: Boolean, date: LocalDate?) {
_isLoading.update { true }
_trainStatus.update { ViewState.Loading }
if (isLive) {
loadTrainStatus(train, date = date) //loads live status using API data
} else {
loadSchedule(train = train) // loads data from room
}
}
//////////////////////////////////////////
private fun loadSchedule(
train: String,
) {
viewModelScope.launch {
try {
withContext(Dispatchers.IO) {
val localSch = localSchCache[train] ?: repo.getSch(train)
.also { localSchCache[train] = it }
val trainSch = trainSchCache[train]
?: mappedTrainToStation(localSch).also {
trainSchCache[train] = it
}
_trainStatus.update { ViewState.Success(data = trainSch) }
}
} catch (exception: Exception) {
_trainStatus.update {
ViewState.Error(
message = exception.message ?: "An unknown error occurred"
)
}
} finally {
_isLoading.update { false }
}
}
}
private fun loadTrainStatus(
train: String,
date: LocalDate? = null,
) {
viewModelScope.launch {
try {
val localData = localSchCache[train] ?: repo.getSch(train)
.also { localSchCache[train] = it }
apiRepo.fetchTrainStatus(train).onSuccess { apiData ->
val mappedData = mappedTrainToStation(localData, apiData)
_trainStatus.update { ViewState.Success(data = mappedData) }
}.onFailure { exception ->
_trainStatus.update {
ViewState.Error(
message = exception.message ?: "An unknown error"
)
}
}
} catch (exception: Exception) {
_trainStatus.update {
ViewState.Error(
message = exception.message ?: "An unknown error occurred"
)
}
} finally {
_isLoading.update { false }
}
}
}
代码按预期运行,我想确保我做的事情是正确的。
你的做法绝对正确,但有很多方法可以优化,每个人都有自己的缓存数据的方法。你使用
localSchCache
和trainSchCache
缓存数据,这很好。但是,一定要小心处理内存泄漏和生命周期变化。ViewModel
生命周期与 UI 生命周期一样长,所以只要 ViewModel 还活着,这种方法就会起作用。关于线程安全和缓存驱逐的建议。