Last active
July 17, 2018 12:53
-
-
Save jerryOkafor/187c5a7892b2ea6875b0e48477d8218d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Data class that is necessary for a UI to show a listing and interact w/ the rest of the system | |
*/ | |
data class Listing<T>( | |
// the LiveData of paged lists for the UI to observe | |
val pagedList: LiveData<PagedList<T>>, | |
// represents the network request status to show to the user | |
val networkState: LiveData<NetworkState>, | |
// represents the refresh status to show to the user. Separate from networkState, this | |
// value is importantly only when refresh is requested. | |
val refreshState: LiveData<NetworkState>, | |
// refreshes the whole data and fetches it from scratch. | |
val refresh: () -> Unit, | |
// retries any failed requests. | |
val retry: () -> Unit) | |
class DataSource( | |
private val apiService: ApiService, | |
private val retryExecutor: Executor, | |
//You can pass all other extra params that you need here. | |
) : PageKeyedDataSource<Int, Deliverable>() { | |
// keep a function reference for the retry event | |
private var retry: (() -> Any)? = null | |
/** | |
* 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 = SingleLiveEvent<NetworkState>() | |
fun retryAllFailed() { | |
val prevRetry = retry | |
retry = null | |
prevRetry?.let { | |
retryExecutor.execute { | |
it.invoke() | |
} | |
} | |
} | |
override fun loadInitial(params: LoadInitialParams<Int>, callback: LoadInitialCallback<Int, Deliverable>) { | |
Timber.d("Loading initial value") | |
} | |
override fun loadAfter(params: LoadParams<Int>, callback: LoadCallback<Int, Deliverable>) { | |
Timber.d("Load after called. Offset: ${params.key}, Page size: ${params.requestedLoadSize}") | |
} | |
override fun loadBefore(params: LoadParams<Int>, callback: LoadCallback<Int, Deliverable>) { | |
Timber.d("Load before called") | |
//This is never used | |
} | |
} | |
class DataSourceFactory( | |
private val apiservice: ApiService, | |
private val retryExecutor: Executor, | |
//You can pass all other extra params that you need here. | |
) : DataSource.Factory<Int, Deliverable>() { | |
val sourceLiveData = MutableLiveData<DataSource>() | |
override fun create(): DataSource<Int, Deliverable> { | |
val source = DataSource(//Pass all required params here.) | |
sourceLiveData.postValue(source) | |
return source | |
} | |
} | |
//Then on the repository or any other place you are creating your data source | |
fun history(//Pass params here): Listing<Deliverable> { | |
val sourceFactory = DataSourceFactory(//Pass params) | |
val config = PagedList.Config.Builder() | |
.setPageSize(10) | |
.build() | |
val livePageList = LivePagedListBuilder(sourceFactory, config) | |
.build() | |
val refreshState = Transformations.switchMap(sourceFactory.sourceLiveData) { | |
it.initialLoad | |
} | |
return Listing( | |
pagedList = livePageList, | |
networkState = Transformations.switchMap(sourceFactory.sourceLiveData) { | |
it.networkState | |
}, | |
retry = { sourceFactory.sourceLiveData.value?.retryAllFailed() }, | |
refresh = { sourceFactory.sourceLiveData.value?.invalidate() }, | |
refreshState = refreshState | |
) | |
} | |
//The in viewModel, observe network state and trigger retries as follows | |
private val repoResult = //create repo list from rrepository | |
private val transports = Transformations.switchMap(repoResult) { it.pagedList }!! | |
private val networkState = Transformations.switchMap(repoResult) { it.networkState }!! | |
private val refreshState = Transformations.switchMap(repoResult) { it.refreshState }!! | |
//call refresh and retry as follows | |
fun refresh() { | |
repoResult.value?.refresh?.invoke() | |
} | |
fun retry() { | |
val listing = repoResult?.value | |
listing?.retry?.invoke() | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment