Bạn có ý tưởng nào để triển khai mẫu kho lưu trữ với các coroutines NetworkBoundResource và Kotlin không? Tôi biết chúng ta có thể phóng một coroutine với GlobalScope, nhưng nó có thể dẫn đến rò rỉ coroutine. Tôi muốn chuyển một viewModelScope làm tham số, nhưng hơi khó, khi thực hiện (vì kho lưu trữ của tôi không biết CoroutineScope của bất kỳ ViewModel nào).
abstract class NetworkBoundResource<ResultType, RequestType>
@MainThread constructor(
private val coroutineScope: CoroutineScope
) {
private val result = MediatorLiveData<Resource<ResultType>>()
init {
result.value = Resource.loading(null)
@Suppress("LeakingThis")
val dbSource = loadFromDb()
result.addSource(dbSource) { data ->
result.removeSource(dbSource)
if (shouldFetch(data)) {
fetchFromNetwork(dbSource)
} else {
result.addSource(dbSource) { newData ->
setValue(Resource.success(newData))
}
}
}
}
@MainThread
private fun setValue(newValue: Resource<ResultType>) {
if (result.value != newValue) {
result.value = newValue
}
}
private fun fetchFromNetwork(dbSource: LiveData<ResultType>) {
val apiResponse = createCall()
result.addSource(dbSource) { newData ->
setValue(Resource.loading(newData))
}
result.addSource(apiResponse) { response ->
result.removeSource(apiResponse)
result.removeSource(dbSource)
when (response) {
is ApiSuccessResponse -> {
coroutineScope.launch(Dispatchers.IO) {
saveCallResult(processResponse(response))
withContext(Dispatchers.Main) {
result.addSource(loadFromDb()) { newData ->
setValue(Resource.success(newData))
}
}
}
}
is ApiEmptyResponse -> {
coroutineScope.launch(Dispatchers.Main) {
result.addSource(loadFromDb()) { newData ->
setValue(Resource.success(newData))
}
}
}
is ApiErrorResponse -> {
onFetchFailed()
result.addSource(dbSource) { newData ->
setValue(Resource.error(response.errorMessage, newData))
}
}
}
}
}
}
NetworkBoundResource
. Nhận xét của tôi tổng quát hơn: IMHO, một triển khai kho lưu trữ của Kotlin sẽ phơi bày các API liên quan đến coroutines.
suspend
hàm hoặc returnChannel
/Flow
object, tùy thuộc vào bản chất của API. Các coroutines thực tế sau đó được thiết lập trong viewmodel.LiveData
được giới thiệu bởi viewmodel, không phải kho lưu trữ.