Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save vamsitallapudi/dcb53dae4751f7e1bafa4654128f4607 to your computer and use it in GitHub Desktop.
Save vamsitallapudi/dcb53dae4751f7e1bafa4654128f4607 to your computer and use it in GitHub Desktop.
PageKeyedNearlensStoryDataSource.kt
package com.coderefer.nearlens.ui.storyList.data
import android.content.Context
import androidx.lifecycle.MutableLiveData
import androidx.paging.PageKeyedDataSource
import com.coderefer.nearlens.data.models.Story
import com.coderefer.nearlens.domain.api.NearlensService
import com.coderefer.nearlens.exceptions.APIException
import com.coderefer.nearlens.util.LIST_SCREEN_STORY_LIMIT
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.IOException
import java.util.concurrent.Executor
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
/**
* A data source that uses the before/after keys returned in page requests.
*
*
* Contributors:
* Vamsi Tallapudi
*/
class PageKeyedNearlensStoryDataSource(
private val service: NearlensService,
private val retryExecutor: Executor
) : PageKeyedDataSource<String, Story>(), CoroutineScope {
override val coroutineContext: CoroutineContext
get() = Dispatchers.IO
@Inject
lateinit var context: Context
/**
* There is no sync on the state because paging will always call loadInitial first then wait
* for it to return some success value before calling loadAfter.
*/
val networkState = MutableLiveData<NetworkState>()
val initialLoad = MutableLiveData<NetworkState>()
override fun loadInitial(
params: LoadInitialParams<String>,
callback: LoadInitialCallback<String, Story>
) {
networkState.postValue(NetworkState.LOADING)
initialLoad.postValue(NetworkState.LOADING)
launch(coroutineContext) {
requestStories(params, callback, LIST_SCREEN_STORY_LIMIT)
}
}
fun retryAllFailed() {
val prevRetry = retry
retry = null
prevRetry?.let {
retryExecutor.execute {
it.invoke()
}
}
}
// private suspend fun fetchStories(
// params: LoadInitialParams<String>,
// callback: LoadInitialCallback<String, Story>,
// limit: Int
// ) = safeApiCall(
// call = { requestStories(params, callback, limit) },
// errorMessage = "Error fetching Stories"
// )
private suspend fun requestStories(
params: LoadInitialParams<String>,
callback: LoadInitialCallback<String, Story>,
limit: Int
) {
try {
val response = service.storyListAsync(limit).await()
if (response.isSuccessful) {
val storiesList = response.body()?.results ?: emptyList()
retry = null
networkState.postValue(NetworkState.LOADED)
initialLoad.postValue(NetworkState.LOADED)
callback.onResult(storiesList, response.body()?.previous, response.body()?.next)
}
} catch (e: IOException) {
retry = {
loadInitial(params, callback)
}
val error = NetworkState.error(e.message ?: "unknown error")
networkState.postValue(error)
initialLoad.postValue(error)
} catch (e: APIException) {
val error = NetworkState.error(e.message ?: "Api Exception")
networkState.postValue(error)
initialLoad.postValue(error)
}
}
override fun loadAfter(params: LoadParams<String>, callback: LoadCallback<String, Story>) {
networkState.postValue(NetworkState.LOADING)
launch(coroutineContext) {
try {
val response = service.storyListAfterAsync(params.key).await()
if (response.isSuccessful) {
val storiesList = response.body()?.results ?: emptyList()
retry = null
networkState.postValue(NetworkState.LOADED)
initialLoad.postValue(NetworkState.LOADED)
callback.onResult(storiesList, response.body()?.next)
}
} catch (e: IOException) {
retry = {
loadAfter(params, callback)
}
val error = NetworkState.error(e.message ?: "unknown error")
networkState.postValue(error)
initialLoad.postValue(error)
} catch (e: APIException) {
val error = NetworkState.error(e.message ?: "Api Exception")
networkState.postValue(error)
initialLoad.postValue(error)
}
}
}
override fun loadBefore(params: LoadParams<String>, callback: LoadCallback<String, Story>) {
// ignored, since we only ever append to our initial load
}
// keep a function reference for the retry event
private var retry: (() -> Any)? = null
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment