Используя различные учебные пособия, я пришел к выводу, что при создании LivePagedListBuilder в ViewModel я должен передать свой запрос, получающий данные из комнаты, в тогда пусть это работает с помощью BoundaryCallback.
Этот запрос в моем коде выглядит так:
Код: Выделить всё
@Query("SELECT * from repositories_table ORDER BY name DESC")
fun getPagedRepos(): DataSource.Factory
Код: Выделить всё
fun getPagedRepos(): DataSource.Factory {
return repositoriesDao.getPagedRepos()
}
Ниже приведены соответствующие части моего приложения:
Источник данных
Код: Выделить всё
class ReposDataSource(private val contactsRepository: ContactsRepository,
private val scope: CoroutineScope, application: Application): PageKeyedDataSource() {
private var supervisorJob = SupervisorJob()
private val PREFS_NAME = "Paging"
private val sharedPref: SharedPreferences = application.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
override fun loadInitial(
params: LoadInitialParams,
callback: LoadInitialCallback
) {
Log.i("RepoBoundaryCallback", "initialTriggered")
val currentPage = 1
val nextPage = currentPage + 1
executeQuery(currentPage, params.requestedLoadSize) {
callback.onResult(it, null, nextPage)
}
}
override fun loadAfter(params: LoadParams, callback: LoadCallback) {
val currentPage = params.key
val nextPage = currentPage + 1
executeQuery(currentPage, params.requestedLoadSize) {
callback.onResult(it, nextPage)
}
}
override fun invalidate() {
super.invalidate()
supervisorJob.cancelChildren()
}
private fun executeQuery(page: Int, perPage: Int, callback: (List) -> Unit) {
scope.launch(getJobErrorHandler() + supervisorJob) {
savePage("current_page", page)
val repos = contactsRepository.fetchPagedRepos(page, perPage)
callback(repos)
}
}
private fun getJobErrorHandler() = CoroutineExceptionHandler { _, e ->
Log.e(ReposDataSource::class.java.simpleName, "An error happened: $e")
}
private fun savePage(KEY_NAME: String, value: Int){
Log.i("RepoBoundaryCallback", value.toString())
val editor: SharedPreferences.Editor = sharedPref.edit()
editor.putInt(KEY_NAME, value)
editor.commit()
}
Код: Выделить всё
class RepoBoundaryCallback (val repository: ContactsRepository, application: Application) :
PagedList.BoundaryCallback() {
private var callbackJob = Job()
private val coroutineScope = CoroutineScope(
callbackJob + Dispatchers.Main )
private val PREFS_NAME = "Paging"
private val sharedPref: SharedPreferences = application.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
override fun onZeroItemsLoaded() {
Log.i("RepoBoundaryCallback", "onzeroitemstriggered")
super.onZeroItemsLoaded()
fetchUsers(1)
}
override fun onItemAtEndLoaded(itemAtEnd: Repository) {
Log.i("RepoBoundaryCallback", "onitematendriggered")
super.onItemAtEndLoaded(itemAtEnd)
fetchUsers(getCurrentPage("current_page"))
}
private fun fetchUsers(page: Int) {
coroutineScope.launch {
try {
var newRepos = RepoApi.retrofitService.fetchRepos(page)
insertRepoToDb(newRepos)
}
catch (e: Exception){
Log.i("RepoBoundaryCallback", e.toString())
}
}
}
private suspend fun insertRepoToDb(reposList: List){
reposList.forEach{repository.insertRepo(it)}
}
private fun getCurrentPage(KEY_NAME: String): Int{
return sharedPref.getInt(KEY_NAME, 0)
}
Код: Выделить всё
interface RepoApiService {
@GET("/orgs/google/repos")
suspend fun fetchRepos(@Query("page") page: Int,
@Query("per_page") perPage: Int = 15): List
Код: Выделить всё
class RepositoryViewModel (application: Application) : AndroidViewModel(application) {
companion object{
private const val TAG = "RepositoryViewModel"
}
//var reposList: LiveData
>
private var repoBoundaryCallback: RepoBoundaryCallback? = null
var reposList: LiveData? = null
private val repository: ContactsRepository
private var viewModelJob = Job()
private val coroutineScope = CoroutineScope(
viewModelJob + Dispatchers.Main )
init {
val contactsDao = ContactsRoomDatabase.getDatabase(application, viewModelScope).contactsDao()
val contactsExtrasDao = ContactsRoomDatabase.getDatabase(application, viewModelScope).contactsExtrasDao()
val repositoriesDao = ContactsRoomDatabase.getDatabase(application, viewModelScope).repositoriesDao()
val service = RepoApi.retrofitService
repository = ContactsRepository(contactsDao, contactsExtrasDao, repositoriesDao, service)
initializedPagedListBuilder(application)
}
private fun initializedPagedListBuilder(application: Application) {
repoBoundaryCallback = RepoBoundaryCallback(
repository, application
)
val pagedListConfig = PagedList.Config.Builder()
//.setPrefetchDistance(5)
//.setInitialLoadSizeHint(20)
.setEnablePlaceholders(true)
.setPageSize(15).build()
reposList = LivePagedListBuilder(
repository.getPagedRepos(),
pagedListConfig
).setBoundaryCallback(repoBoundaryCallback).build()
}
override fun onCleared() {
super.onCleared()
viewModelJob.cancel()
}
}
Итак, как же связать свой собственный источник данных с BoundaryCallback с помощью Room и модернизировать? Буду благодарен за любую помощь.
Подробнее здесь: https://stackoverflow.com/questions/630 ... rycallback
Мобильная версия