Отладка пагинации с помощью компонента Paging Architecture - PullRequest
0 голосов
/ 19 сентября 2018

Итак, я написал простую функциональность заметок с библиотекой подкачки, используя LiveData и базу данных Room, но я не вижу, чтобы это что-то разбивало на страницы.Возможно, я не отлаживаю правильно, чтобы подтвердить, что нумерация страниц происходит.Любой совет приветствуется.

В моем DAO:

@Query("SELECT * FROM notes ORDER BY id ASC")
fun allNotes(): DataSource.Factory<Int, NoteEntity>

Затем в моем NotesRepository я преобразую из NoteEntity в Note, чтобы сохранить детализацию реализации уровня данных иОстальная часть приложения отдельная (я фанат Чистой Архитектуры).Таким образом, результат будет DataSource.Factory<Int, Note>:

override fun allNotes(): DataSource.Factory<Int, Note> =
        notesDao.allNotes().map { mapper.fromDb(it) }

В моем ViewModel, где PAGE_SIZE равно 20:

val noteList: LiveData<PagedList<Note>> =
        LivePagedListBuilder(
                getNotesUseCase.allNotes(), PAGE_SIZE)

My Note просто:

data class Note(
    val id: Long = 0,
    val text: String
)

Затем я отображаю заметки в RecyclerView.

My ViewHolder содержит:

class NoteViewHolder(parent: ViewGroup) : RecyclerView.ViewHolder(
    LayoutInflater.from(parent.context).inflate(R.layout.note_item, parent, false))  {
   private val idView = itemView.findViewById<TextView>(R.id.noteId)
   private val nameView = itemView.findViewById<TextView>(R.id.noteText)
   private var note: Note? = null

   /**
    * Items might be null if they are not paged in yet. PagedListAdapter will re-bind the
    * ViewHolder when Item is loaded.
    */
    fun bindTo(note: Note?) {
        this.note = note
        idView.text = note?.let { it.id.toString() } ?: ""
        nameView.text = note?.text ?: ""
    }
}

My Adapter содержит:

class NoteAdapter(
    private val clickListener: ClickListener) : PagedListAdapter<Note, NoteViewHolder>(diffCallback) {

override fun onBindViewHolder(holder: NoteViewHolder, position: Int) {
    Timber.d("Binding view holder at position $position")
    val note = getItem(position)

    with(holder) {
        bindTo(note)
        note?.let {
            itemView.setOnClickListener {
            clickListener(note)
        }
    }
}

}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NoteViewHolder =
        NoteViewHolder(parent)

companion object {
    /**
     * This diff callback informs the PagedListAdapter how to compute list differences when new
     * PagedLists arrive.
     */
    private val diffCallback = object : DiffUtil.ItemCallback<Note>() {
        override fun areItemsTheSame(oldItem: Note, newItem: Note): Boolean =
                oldItem.id == newItem.id

        override fun areContentsTheSame(oldItem: Note, newItem: Note): Boolean =
                oldItem == newItem
        }
    }
}

И мой Fragment содержит:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    setupRecyclerView()

    viewModel = ViewModelProviders.of(this, noteListViewModelFactory).get(NoteListViewModel::class.java)
    viewModel.noteList.observe(this, Observer { pagedNoteList ->
        pagedNoteList?.let { render(pagedNoteList) }
    })
}

private fun render(pagedNoteList: PagedList<Note>) {
    recyclerViewAdapter.submitList(pagedNoteList)
}

Данные в RecyclerView загружены успешно, и я вижу журналы отладки, когда каждый элемент связан. Насколько я понимаю, PagedListAdapter Я использую запросы на новые страницы, когда пользователь прокручивает и обрабатывает новые PagedList s, вычисляя различия в фоновом потоке.

Мой источник данных содержит 100 элементов, поэтомуЯ ожидаю, что при размере страницы 20 при тестировании на телефоне среднего размера будет сделано 5 вызовов данных.

Как мне отладить это, чтобы обеспечить правильное количество вызовов?Кроме того, в приведенной выше реализации один из них используется по умолчанию (PositionalDataSource, ItemKeyedDataSource или PageKeyedDataSource)?

1 Ответ

0 голосов
/ 20 сентября 2018

Отвечая на мой собственный вопрос:

Похоже, что в комнате PositionalDataSource используется по умолчанию.

Мне удалось выяснить, как мои заметки загружаются в чанках, добавив следующий оператор журнала внутри моего NoteAdapter.onBindViewHolder():

Log.d("NoteAdapter", currentList)

, где currentList является свойствомсуперкласс PagedListAdapter.

/**
 * Returns the PagedList currently being displayed by the Adapter.
 * etc.
 */
@Nullable
public PagedList<T> getCurrentList() {
    return mDiffer.getCurrentList();
}

По мере прокрутки пользователя новые элементы привязываются к держателю просмотра, а в журнале отображается содержимое currentList, которое повторяется.

Также обратите внимание, что при установке размера страницы на N начальный размер списка будет содержать счетчик 3 * N.Затем каждый раз, когда пользователь прокручивает их все, на currentList будет добавлено N больше предметов.Это потому, что я использовал конфигурацию по умолчанию при запросе списка страниц:

val noteList: LiveData<PagedList<Note>> =
        LivePagedListBuilder(
                getNotesUseCase.allNotes(), PAGE_SIZE)
                .build()

Вместо этого я мог бы сделать что-то подобное для управления initialLoadSizeHint:

private val pagedListConfig = PagedList.Config.Builder()
        .setEnablePlaceholders(true)
        .setInitialLoadSizeHint(INITIAL_LOAD_SIZE)
        .setPageSize(PAGE_SIZE)
        .build()

val noteList = LivePagedListBuilder<Int,Note>(getNotesUseCase.allNotes(), pagedListConfig).build()

По умолчанию initialLoadSizeHint равно PAGE_SIZE * 3.

...