Почему этот пример библиотеки подкачки работает намного хуже, чем просто представление переработчика? - PullRequest
0 голосов
/ 28 октября 2018

Итак, я читал о новой библиотеке подкачки Android.В частности, я пытаюсь загрузить список бесконечных изображений (с Glide), используя обзор повторного просмотра с адаптером, моделью представления и источником данных (поддержанный сетевыми вызовами дооснащения).

Вот базовый код:

// inside my activity
PhotosListAdapter adapter = new PhotosListAdapter(getApplicationContext());

PhotosViewModel viewModel = ViewModelProviders.of(this).get(PhotosViewModel.class);

viewModel.getPhotosList().observe(this, adapter::submitList);

RecyclerView recyclerView = findViewById(R.id.main_recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(adapter);

...

// My adapter code:
@Override
public void onBindViewHolder(@NonNull PhotoViewHolder photoViewHolder, int i) {
    Photo photo = getItem(i);
    if (photo != null) {
        mGlide.load(photo.previewURL).into(photoViewHolder.mPhotoImageView);
    }

}

private static final DiffUtil.ItemCallback<Photo> DIFF_CALLBACK = new DiffUtil.ItemCallback<Photo>() {
    @Override
    public boolean areItemsTheSame(@NonNull Photo photo, @NonNull Photo other) {
        return photo.id == other.id; // these are just ints
    }

    @Override
    public boolean areContentsTheSame(@NonNull Photo photo, @NonNull Photo other) {
        return photo.previewURL.equals(other.previewURL); // this is just a string
    }
};

...

// My View Model code:
private LiveData<PagedList<Photo>> mData;

public PhotosViewModel() {
    PhotosDataSource photosDataSource = new PhotosDataSource();
    mData = new LivePagedListBuilder<>(new DataSource.Factory<Integer, Photo>() {
        @Override
        public DataSource<Integer, Photo> create() {
            return photosDataSource;
        }
    }, 25).build();
}

public LiveData<PagedList<Photo>> getPhotosList() {
    return mData;
}

// My Data Source:
Call<SearchResult> search = mPixabayService.search(PixabayApi.api_key, "photo", 1, params.requestedLoadSize, true);
    search.enqueue(new Callback<SearchResult>() {
        @Override
        public void onResponse(Call<SearchResult> call, Response<SearchResult> response) {
            if (response.isSuccessful()) {
                SearchResult body = response.body();
                callback.onResult(body.hits, null, 2);
            }
            // TODO add error cases
        }

        @Override
        public void onFailure(Call<SearchResult> call, Throwable t) {

        }
    });

 @Override
public void loadAfter(@NonNull LoadParams params, @NonNull LoadCallback callback) {
    Call<SearchResult> result = mPixabayService.search(PixabayApi.api_key, "photo", (Integer)params.key, params.requestedLoadSize, true);
    result.enqueue(new Callback<SearchResult>() {
        @Override
        public void onResponse(Call<SearchResult> call, Response<SearchResult> response) {
            if (response.isSuccessful()) {
                List<Photo> hits = response.body().hits;
                callback.onResult(hits, (Integer)params.key + 1);
            }
        }

        @Override
        public void onFailure(Call<SearchResult> call, Throwable t) {

        }
    });
}

Тем не менее, я построил тот же пример только с использованием адаптера статического списка элементов, и это, кажется, гораздо более плавно прокручивается в моем эмуляторе.Есть что-то, что я пропускаю в своем коде

Вот мои подозрения относительно факторов, которые могут усугубить ситуацию:

  1. имеет ли смысл recyclerview.setHasFixedSize(true) в этом случае?(Я также заметил, что изображения имеют разные размеры, когда я прокручиваю вниз и затем возвращаюсь к исходному изображению - есть ли способ предотвратить это?)
  2. это из-за чего-то странного в DIFF_CALLBACK?я на самом деле не знаю цели этого класса, что
  3. viewModel.getPhotosList().observe(this, adapter::submitList);, как ожидается, будет медленнее, потому что это должно сделать список недействительным (против статического списка);тем не менее, ожидается ли, что это приведет к 5-кратному отставанию ??!
  4. Я заметил, что довольно быстро переключаюсь на эмулятор, что, по-видимому, не является проблемой для статического рециркулятора;однако делает ли LivePage что-то другое для обнаружения их броска?экран, кажется, сходит с ума, когда я бросаю.Другими словами, является ли моя воспринимаемая «неровная производительность из библиотеки подкачки страниц» только потому, что я переключаюсь вверх и вниз (в отличие от медленной прокрутки вверх и вниз)?
  5. Я просто теряю пропущенный параметр конфигурации ключагде-то?

1 Ответ

0 голосов
/ 28 октября 2018

Разумеется, статический список будет более плавным - гораздо меньше накладных расходов.Если это реальная возможность, пойти с этим.Вы используете список с постраничной загрузкой, когда удержание всего списка в памяти невозможно или когда запрос всего списка из источника данных (особенно удаленного) будет слишком трудоемким / дорогостоящим.

1) Зависит от вашего интерфейса.Фиксированный размер - это размер, который он принимает на экране, а не размер списка.Обычно это справедливо для полноразмерных списков или списков, которые не растут / не уменьшаются с содержимым.

2) DiffUtil и его обратный вызов не имеют ничего общего с подкачкой, они уже существовали в библиотеке подкачки.Они разбирают списки вокруг изменений, чтобы сделать наиболее эффективные вызовы адаптера возможными, вместо того, чтобы делать весь notifyDataSetChanged.Но они занимают некоторое время при этом.Важно, чтобы это было правильно, иначе вы либо пропустите уведомления, либо будете использовать менее эффективные.

3) Ожидается, что он будет медленнее, чем что?Но везде, где вы используете наблюдаемую информацию, вы увидите замедление, потенциально вы публикуете сообщения между потоками.Это одна из причин, по которой они ужасно часто злоупотребляют, люди не понимают, что они на самом деле делают.Да, замедление в 5 раз не кажется маловероятным, особенно если вы в конечном итоге используете менее эффективный метод notifyDataSetChanged, а не более точные уведомления.

4) Когда вы бросаете, вы загружаете намного больше элементов быстрее.Который может вызвать больше удаленных нагрузок.Так что, если у вас возникнут проблемы, это будет, когда вы бросаете.Обычно вы хотите предварительно загрузить отдельный поток достаточно заранее, это не проблема.Вы пробовали играть с размером страницы и расстоянием предварительной выборки?

...