Nano Hash - криптовалюты, майнинг, программирование

RecyclerView с загрузчиком курсора работает слишком медленно при частом обновлении

Я извлекаю канал подкаста из БД и отображаю его в RecyclerView с помощью LoaderManager.LoaderCallbacks. В моем контент-провайдере:

  1. Я регистрирую «Наблюдатель» в методе запроса () преобразователя содержимого с помощью: cursor.setNotificationUri(getContext().getContentResolver(), uri);
  2. Когда я обновляю/вставляю/удаляю в преобразователе контента, я уведомляю Observer с помощью: getContext().getContentResolver().notifyChange(uri, null);, поэтому onLoaderReset() запускается при необходимости

Затем у меня есть служба с DownloadManager, которая каждую секунду обновляет ход моих текущих загрузок в базу данных. Загрузчик постоянно загружает данные из БД, и я вижу изменение хода каждого эпизода загрузки в пользовательском интерфейсе.

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

Моя пользовательская активность с RecyclerView

public class MyActivity
    implements LoaderManager.LoaderCallbacks<Cursor> {

    private RecyclerView mRecyclerView;
    private MyCustomRecyclerViewAdapter mAdapter;

    ...

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        return new CursorLoader(this,
            myDataUri, null, null, null, null
        );  
    }   

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        mAdapter.swapCursor(data);
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        mAdapter.swapCursor(null);
    }

    ...
}

Мой пользовательский адаптер

public class MyCustomRecyclerViewAdapter
    extends RecyclerView.Adapter<EpisodeAdapter.AudioAdapterViewHolder> {

    ...

    public void swapCursor(Cursor newCursor) {
        mCursor = newCursor;
        notifyDataSetChanged();
    }

    ... 
}

Ответы:


1

ReclyclerView намного эффективнее (особенно метод notifyDataSetChanged()), когда адаптер имеет стабильные идентификаторы.

Если ваши данные имеют идентификаторы (например, из БД), вам действительно следует подумать о том, чтобы ваш адаптер использовал setHasStableIds(true) и правильно переопределить getItemId(int position).

Я не уверен, что это полностью решит вашу проблему, но это определенно хорошая практика.

27.01.2016
  • Я не могу использовать setHasStableIds(true) из-за ограничения: Невозможно изменить, имеет ли этот адаптер стабильные идентификаторы, пока в адаптере зарегистрированы наблюдатели.. Идентификаторы не меняются, но связанные данные меняются, поэтому это невозможно. Но спасибо за ваш совет. 27.01.2016
  • setHasStableIds(true) обычно вызывается только в конструкторе. Стабильный идентификатор означает, что один и тот же элемент имеет один и тот же идентификатор, это не означает, что данные (содержимое элемента) не меняются (такая оптимизация может быть выполнена с использованием полезных нагрузок в последней версии RecyclerView) 27.01.2016
  • спасибо, просто забыл реализовать getItemId(int position)... теперь работает, но все равно тихо вяло (из-за переключения курсора). 27.01.2016
  • Я предполагаю, что обновление каждую секунду - это слишком быстро. Просто из любопытства, оптимизация стабильных идентификаторов немного помогла или совсем не помогла? 28.01.2016

  • 2

    Не используйте notifyDataSetChanged(), а notifyItemInserted() или notifyItemRangeInserted() для повышения производительности.

    для аналогичной проблемы, которая была решена, см. в этом

    27.01.2016
  • ViewHolder мерцает при использовании notifyItemChanged(), и все же это очень неэффективно, а прокрутка не плавная. Идея в том, что менять весь курсор каждую секунду или каждые полсекунды нехорошо. Я думаю, что зарегистрировать какой-нибудь широковещательный приемник для загрузки элемента было бы более эффективно, но его нужно будет зарегистрировать в onBindViewHolder(), но это тоже не очень хорошая практика. 27.01.2016
  • Все, что работает без сбоев, выглядит приемлемо и выполняет свою работу, является хорошей практикой, ИМХО. 27.01.2016
  • Итак, когда я регистрирую BroadcastReceiver для элемента ViewHolder в onBindViewHolder, чтобы получать данные о ходе выполнения, а не извлекать их из БД, когда я могу отменить его регистрацию? 27.01.2016
  • в onPause() и onFinish() конечно. и перерегистрируйтесь в onResume() 27.01.2016
  • Нет, речь идет об адаптере RecyclerView и о присоединении приемника к элементу в списке - в методе onBindViewHolder() нет onPause() и т.д... 27.01.2016
  • Вам либо понадобятся обратные вызовы, либо попробуйте жить без отмены регистрации получателей, что, надеюсь, не вызовет (многих) сбоев. 27.01.2016
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..