NetworkBoundResource およびKotlinコルーチンを使用してリポジトリパターンを実装する方法について何かアイデアはありますか? GlobalScopeを使用してコルーチンを起動できることはわかっていますが、コルーチンのリークにつながる可能性があります。 viewModelScopeをパラメーターとして渡したいのですが、実装に関しては少しトリッキーです(私のリポジトリは、任意のViewModelのCoroutineScope)。
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))
}
}
}
}
}
}
Kotlin Coroutineは初めてです。今週、この問題に遭遇しました。
上記の投稿で述べたようにリポジトリパターンを使用する場合、私の意見ではCoroutineScopeをNetworkBoundResourceに自由に渡すことができます。 CoroutineScopeはRepositoryの関数のパラメーターの1つであり、次のようなLiveDataを返します。
suspend fun getData(scope: CoroutineScope): LiveDate<T>
ViewModelでgetData()を呼び出すときに、組み込みスコープviewmodelscopeをCoroutineScopeとして渡すため、NetworkBoundResourceがviewmodelscopeおよびViewmodelのライフサイクルにバインドされます。 ViewBが無効になると、NetworkBoundResourceのコルーチンがキャンセルされます。これはメリットになります。
組み込みスコープviewmodelscopeを使用するには、build.gradleに以下を追加することを忘れないでください。
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0-alpha01'