Урок 14. Paging Library. Основы

Ответить
Аватара пользователя
damager82
Администратор
Сообщения: 1383
Зарегистрирован: 07 янв 2012, 11:32
Контактная информация:

Урок 14. Paging Library. Основы

Сообщение damager82 » 20 мар 2018, 02:08

В этом уроке начнем знакомство с Paging Library. Рассмотрим общую схему работы связки PagedList и DataSource. 


Click here to read this article!
Последний раз редактировалось damager82 25 июн 2018, 12:51, всего редактировалось 18 раз.
Добро пожаловать на форум сайта StartAndroid
ИзображениеИзображение

wondertalik
Сообщения: 15
Зарегистрирован: 29 мар 2013, 10:15

Re: Урок 14. Paging Library. Основы

Сообщение wondertalik » 20 июл 2018, 21:59

Некоторые уточнения, ссылка
API changes to clarify the role of executors in builders:

Renamed setBackgroundThreadExecutor() to setFetchExecutor() (in PagedList.Builder and LivePagedListBuilder)

Renamed setMainThreadExecutor() to setNotifyExecutor() (in PagedList.Builder).

Fixed PagedList.mCallbacks member to be private.
Поэтому код для pageList немного изменился

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

  PagedList<Client> pagedList = new PagedList.Builder<>(dataSource, config)
                .setFetchExecutor(Executors.newSingleThreadExecutor())
                .setNotifyExecutor(new MainThreadExecutor())
                .build();

Reyst.GSI
Сообщения: 3
Зарегистрирован: 23 янв 2019, 09:08

Re: Урок 14. Paging Library. Основы

Сообщение Reyst.GSI » 10 мар 2019, 19:32

Почему может не вызываться получение следующей порции данных?

Сделал, вроде, все по примеру. Начальные 30 записей появляются, а вот следующие нет.

Активити

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

public class MainActivity extends AppCompatActivity {

    final private InfoAdapter adapter = new InfoAdapter(new InfoDiffer());

    final private PagedList.Config config = new PagedList.Config.Builder()
            .setEnablePlaceholders(false)
            .setPageSize(10)
            .build();

    private final InfoStorage storage = new InfoStorage();
    private InfoDataSource dataSource = new InfoDataSource(storage);
    private PagedList<Info> pageList = new PagedList.Builder<>(dataSource, config)
            .setFetchExecutor(Executors.newSingleThreadExecutor())
            .setNotifyExecutor(new MainThreadExecutor())
            .build();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final RecyclerView rvMain = findViewById(R.id.rv_main);
        rvMain.setLayoutManager(new LinearLayoutManager(this));

        adapter.submitList(pageList);
        rvMain.setAdapter(adapter);
    }

    class MainThreadExecutor implements Executor {
        private final Handler handler = new Handler(Looper.getMainLooper());

        @Override
        public void execute(@NonNull Runnable command) {
            handler.post(command);
        }
    }
}
Все что касается данных:

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

data class Info(val id: Int, val name: String) {
    override fun toString() = "$id - $name"
}

class InfoDiffer: DiffUtil.ItemCallback<Info>() {

    override fun areItemsTheSame(oldItem: Info?, newItem: Info?): Boolean = oldItem?.id == newItem?.id

    override fun areContentsTheSame(oldItem: Info?, newItem: Info?) = oldItem == newItem

}

class InfoDataSource(private val storage: InfoStorage): PositionalDataSource<Info>() {

    override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback<Info>) {
        Log.d("INSPECT", "loadInitial, requestedStartPosition = ${params.requestedStartPosition}, requestedLoadSize = ${params.requestedLoadSize}")
        val result = storage.getData(params.requestedStartPosition, params.requestedLoadSize)
        callback.onResult(result, params.requestedStartPosition)
    }

    override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<Info>) {
        Log.d("INSPECT", "loadRange, startPosition = ${params.startPosition}, loadSize = ${params.loadSize}")
        val result = storage.getData(params.startPosition, params.loadSize)
        callback.onResult(result)
    }
}

class InfoStorage {
    fun getData(startPosition: Int, loadSize: Int): MutableList<Info> {
        val endPos = minOf(startPosition + loadSize - 1, 100)
        return (startPosition..endPos).map { Info(it + 1, "Info num ${it + 1}") } as MutableList<Info>
    }
}
Адаптер и вьюхолдер:

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

class InfoAdapter(itemDiffer: DiffUtil.ItemCallback<Info>) : PagedListAdapter<Info, InfoVH>(itemDiffer) {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): InfoVH {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item, parent, false)
        return InfoVH(view)
    }

    override fun onBindViewHolder(holder: InfoVH, position: Int) {
        currentList?.get(position)?.also { holder.bind(it) }
    }

}

class InfoVH(itemView: View) : RecyclerView.ViewHolder(itemView) {
    fun bind(item: Info) {
        (itemView as TextView).text = item.toString()
    }
}
проблема решена:

Для того чтобы все работало обязательно надо вызывать метод getItem(position) вместо других способов получения значения по индексу, например currentList?.get(position)

Fenris
Сообщения: 1
Зарегистрирован: 19 мар 2019, 14:28

Re: Урок 14. Paging Library. Основы

Сообщение Fenris » 19 мар 2019, 14:32

А где-то можно посмотреть полный код урока?

mrSOM
Сообщения: 1
Зарегистрирован: 19 ноя 2019, 00:40

Re: Урок 14. Paging Library. Основы

Сообщение mrSOM » 19 ноя 2019, 00:41

Ну что нашли?

m4xp1
Сообщения: 1
Зарегистрирован: 27 дек 2019, 18:45

Re: Урок 14. Paging Library. Основы

Сообщение m4xp1 » 27 дек 2019, 18:49

Очень важно! Метод:

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

 public void loadInitial(@NonNull LoadInitialParams params, @NonNull LoadInitialCallback<Employee> callback) 
Должен отрабатывать синхронно! То есть данные должны быть загруженны и переданны в callback до того как метод loadInitial закончит свое выполнение. Иначе при вызове invalidate у DataSource ваш список будет перепрыгивать на позицию 0.

PS: Было бы здорово если бы автор урока добавил эту информацию в сам урок. Я в свое время убил целый день пытаясь найти причину своей ошибки, хорошо бы если остальные не наступят на эти грабли.

Ответить