Как объединить мои собственные DataDource и BoundaryCallback?Android

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Как объединить мои собственные DataDource и BoundaryCallback?

Сообщение Anonymous »

Я создаю приложение на основе базы данных + сети и API GitHub rest.
Используя различные учебные пособия, я пришел к выводу, что при создании 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()
}
BoundaryCallback

Код: Выделить всё

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)
}
Запрос API

Код: Выделить всё

interface RepoApiService {
@GET("/orgs/google/repos")
suspend fun fetchRepos(@Query("page") page: Int,
@Query("per_page") perPage: Int = 15): List
ViewModel

Код: Выделить всё

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()
}
}
Кроме того, я сохраняю соответствующие страницы в SharedPreferences в DataSource, чтобы затем использовать их в соответствующих функциях BoundaryCallback.
Итак, как же связать свой собственный источник данных с BoundaryCallback с помощью Room и модернизировать? Буду благодарен за любую помощь.


Подробнее здесь: https://stackoverflow.com/questions/630 ... rycallback
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»