Мерцание изображения при прокрутке в RecyclerView

я пытаюсь отобразить список песен, найденных на устройстве, запрашивающем данные непосредственно из MediaStore. Я использую RecyclerView и адаптер, который использует CursorAdapter для получения данных из MediaStore. Когда адаптер onBindViewHolder вызывается, запрос передается в

3 ответов


я решил, добавив поле в ViewHolder содержащий AsyncTask относительно этого элемента. В bindView функция I fisrt установить AsyncTask.cancel(true) и, внутри задачи я сделал чек isCancelled() перед применением полученного изображения с помощью Picasso.with(...).load(...). Это само решена мерцание.

компании bindview

if(holder.downloadImageTask != null)
      holder.downloadImageTask.cancel(true);

      holder.downloadImageTask = (DownloadImageTask) new DownloadImageTask(mediaStoreHelper, context, holder.imgArt).execute(holder.album_id);

AsyncTask

private class DownloadImageTask extends AsyncTask<String, String, String> {

        private MediaStoreHelper mediaStoreHelper;
        private ImageView imageView;
        private Context context;

        public DownloadImageTask(MediaStoreHelper mediaStoreHelper, Context context, ImageView imageView)
        {
            this.mediaStoreHelper = mediaStoreHelper;
            this.context = context;
            this.imageView = imageView;
        }
        @Override
        protected String doInBackground(String... ids) {
            return mediaStoreHelper.getAlbumArtPath(ids[0]);
        }

        protected void onPostExecute(String result) {
            if(!isCancelled())
                Picasso.with(context)
                        .load(new File(result))
                        .placeholder(R.drawable.ic_music)
                        .fit()
                        .into(imageView);
        }
    }

для полноты, это также удалить изображение из переработанных элементов и установить заполнитель.

@Override
public void onViewRecycled(SongViewHolder holder) {
    super.onViewRecycled(holder);
    Picasso.with(holder.itemView.getContext())
            .cancelRequest(holder.imgArt);
    Picasso.with(holder.itemView.getContext())
            .load(R.drawable.ic_music)
            .fit()
            .into(holder.imgArt);
}

это решение заставило меня думать, что проблема времени intercurring внутри AsyncTask между извлечением изображения из MediaStore и временем, когда изображение фактически применяется в ImageView от Пикассо.


комментировать эти строки

мерцание происходит, потому что bind не вызывает только один раз для одного элемента, поэтому он вызывает снова и снова для одной строки, и вы устанавливаете null каждый раз, а также устанавливаете представление на нем. производя мерцание.

 Picasso.with(holder.imgArt.getContext())
                    .cancelRequest(holder.imgArt);
            holder.imgArt.setImageDrawable(null);

асинхронный задач используется совершенно неправильно.

во-первых, вы никогда не должны выполнять анонимный асинхронных задач.

во-вторых, избавьтесь от этой асинхронной задачи в адаптере, потому что это, похоже, вызывает проблему.

получить данные для адаптера, а затем показать его.

кстати, завершение Пикассо лучше сделать так:

       @Override public void onViewRecycled(VH holder) {
            super.onViewRecycled(holder);
            Picasso.with(holder.itemView.getContext())
                   .cancelRequest(holder.getImageView());
        }