Пейджинговая библиотека без комнаты

Все примеры новой библиотеки подкачки были с библиотекой 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.

Другие вопросы по тегам