Пейджинговая библиотека без комнаты
Все примеры новой библиотеки подкачки были с библиотекой Room, и Room создает источник данных для нас. В моем собственном случае мне нужно создать свой собственный источник данных.
Вот метод в моем классе модели представления, который должен возвращать живые данные. Моя жилпата всегда возвращает ноль.
LiveData<PagedList<ApiResult>> getData(){
LivePagedListProvider<Integer,ApiResult> p = new LivePagedListProvider<Integer, ApiResult>() {
@Override
protected DataSource<Integer, ApiResult> createDataSource() {
return new DataClass();
}
};
listLiveData = p.create(0,new PagedList.Config.Builder()
.setPageSize(5) //number of items loaded at once
.setPrefetchDistance(0)// the distance to the end of already loaded list before new data is loaded
.build());
return listLiveData;
}
А вот класс данных
public class DataClass extends TiledDataSource<ApiResult> {
private List<ApiResult> result = new ArrayList<>();
@Override
public int countItems() {
return result.size();
}
@Override
public List<ApiResult> loadRange(int startPosition, int count) {
Call<String> call = NetworkModule.providesWebService().makeRequest();
call.enqueue(new Callback<String>() {
@Override
public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) {
Log.i(DataClass.this.getClass().getSimpleName() + " - onResponse", String.valueOf(response));
result = parseJson(response.body());
}
@Override
public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) {
Log.i(DataClass.this.getClass().getSimpleName() + " - onFailure", t.getMessage());
}
});
return result;
}
}
2 ответа
Я думаю, что это может помочь:
1. countItems () должна вернуть DataSource.COUNT_UNDEFINED
2. loadRange (int startPosition, int count): вы можете напрямую выполнить ваш запрос.
3. Так что теперь вы можете удалить результат глобальной переменной
Кроме того, выключатели-заполнители:
listLiveData = p.create(0,new PagedList.Config.Builder()
.setPageSize(5) //number of items loaded at once
.setPrefetchDistance(10) //Must be >0 since placeholders are off
.setEnablePlaceholders(false)
.build());
Вот обновленный код для класса данных:
public class DataClass extends TiledDataSource<ApiResult> {
@Override
public int countItems() {
return DataSource.COUNT_UNDEFINED;
}
@Override
public List<ApiResult> loadRange(int startPosition, int count) {
Call<String> call = NetworkModule.providesWebService().makeRequest();
Response<String> response = call.execute();
return parseJson(response.body());
}
Вы можете проверить пример проекта здесь: https://github.com/brainail/.samples/tree/master/ArchPagingLibraryWithNetwork
Вы можете создать пользовательский источник данных, обычно мы создаем внутренний API-интерфейс для извлечения данных, который принимает pagenumber в качестве параметра для возврата указанной страницы.
Для этой ситуации вы можете использовать PageKeyedDataSource. Вот пример кода PageKeyedDataSource с использованием API Stackru. Приведенный ниже код использует Retrofit для получения данных из API Stackru.
public class ItemDataSource extends PageKeyedDataSource<Integer, Item> {
//the size of a page that we want
public static final int PAGE_SIZE = 50;
//we will start from the first page which is 1
private static final int FIRST_PAGE = 1;
//we need to fetch from stackru
private static final String SITE_NAME = "stackru";
//this will be called once to load the initial data
@Override
public void loadInitial(@NonNull LoadInitialParams<Integer> params, @NonNull final LoadInitialCallback<Integer, Item> callback) {
RetrofitClient.getInstance()
.getApi().getAnswers(FIRST_PAGE, PAGE_SIZE, SITE_NAME)
.enqueue(new Callback<StackApiResponse>() {
@Override
public void onResponse(Call<StackApiResponse> call, Response<StackApiResponse> response) {
if (response.body() != null) {
callback.onResult(response.body().items, null, FIRST_PAGE + 1);
}
}
@Override
public void onFailure(Call<StackApiResponse> call, Throwable t) {
}
});
}
//this will load the previous page
@Override
public void loadBefore(@NonNull final LoadParams<Integer> params, @NonNull final LoadCallback<Integer, Item> callback) {
RetrofitClient.getInstance()
.getApi().getAnswers(params.key, PAGE_SIZE, SITE_NAME)
.enqueue(new Callback<StackApiResponse>() {
@Override
public void onResponse(Call<StackApiResponse> call, Response<StackApiResponse> response) {
//if the current page is greater than one
//we are decrementing the page number
//else there is no previous page
Integer adjacentKey = (params.key > 1) ? params.key - 1 : null;
if (response.body() != null) {
//passing the loaded data
//and the previous page key
callback.onResult(response.body().items, adjacentKey);
}
}
@Override
public void onFailure(Call<StackApiResponse> call, Throwable t) {
}
});
}
//this will load the next page
@Override
public void loadAfter(@NonNull final LoadParams<Integer> params, @NonNull final LoadCallback<Integer, Item> callback) {
RetrofitClient.getInstance()
.getApi()
.getAnswers(params.key, PAGE_SIZE, SITE_NAME)
.enqueue(new Callback<StackApiResponse>() {
@Override
public void onResponse(Call<StackApiResponse> call, Response<StackApiResponse> response) {
if (response.body() != null) {
//if the response has next page
//incrementing the next page number
Integer key = response.body().has_more ? params.key + 1 : null;
//passing the loaded data and next page value
callback.onResult(response.body().items, key);
}
}
@Override
public void onFailure(Call<StackApiResponse> call, Throwable t) {
}
});
}
}
Здесь вы можете видеть, что мы получаем результат, делая вызов Retrofit, а затем отправляем результат в обратный вызов.
Подробное пошаговое описание приведено в этом руководстве по библиотеке подкачки Android.