Você tem alguma idéia de como implementar o padrão de repositório com as rotinas de rede NetworkBoundResource e Kotlin? Sei que podemos lançar uma corotina dentro de um GlobalScope, mas isso pode levar ao vazamento de corotina. Gostaria de passar um viewModelScope como parâmetro, mas é um pouco complicado quando se trata de implementação (porque meu repositório não conhece um CoroutineScope de nenhum ViewModel).
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
. Meus comentários são mais gerais: IMHO, uma implementação de repositório Kotlin deve expor APIs relacionadas a corotinas.
LiveData
não possui o poder das corotinas RxJava ou Kotlin. LiveData
é muito bom para as comunicações da "última milha" da atividade ou fragmento e foi projetado com isso em mente. E para aplicativos pequenos, se você quiser pular repositórios e apenas ViewModel
conversar diretamente com um RoomDatabase
, tudo LiveData
bem.
suspend
funções ou retornarChannel
/Flow
objetos, dependendo da natureza da API. As reais rotinas são configuradas no modelo de exibição.LiveData
é apresentado pelo viewmodel, não pelo repositório.