【问题标题】:Prevent RecyclerView showing previous content when scrolling防止 RecyclerView 在滚动时显示以前的内容
【发布时间】:2015-09-19 11:30:32
【问题描述】:

我有一个带有 GridLinearLayout 和自定义适配器的 RecyclerView。每一项的内容是一张使用json下载并解析的图片。

基本上是一个图片网格。

一切正常,但是,当向下滚动内容并再次向上滚动时,它会在不到一秒钟的时间内显示每个项目中的先前视图,然后再次显示正确的图片。

我可以做些什么来防止或解决这个问题?提前感谢您提供的任何帮助和/或指导。

这是适配器代码:

package jahirfiquitiva.project.adapters;

import android.content.Context;
import android.graphics.Bitmap;
import android.support.v7.graphics.Palette;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;

import jahirfiquitiva.project.activities.WallpapersActivity;
import com.koushikdutta.async.future.FutureCallback;
import com.koushikdutta.ion.Ion;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;

import jahirfiquitiva.project.R;

public class WallpapersAdapter extends RecyclerView.Adapter<WallpapersAdapter.WallsHolder> {

    public interface ClickListener {
        void onClick(WallsHolder view, int index, boolean longClick);
    }

    private ArrayList<HashMap<String, String>> data;
    private final Context context;
    private boolean usePalette = true;
    private final ClickListener mCallback;
    private final Map<String, Palette> mPaletteCache = new WeakHashMap<>();

    public WallpapersAdapter(Context context, ClickListener callback) {
        this.context = context;
        this.data = new ArrayList<>();
        this.mCallback = callback;
    }

    public void setData(ArrayList<HashMap<String, String>> data) {
        this.data = data;
        notifyDataSetChanged();
    }

    @Override
    public WallsHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(context);
        return new WallsHolder(inflater.inflate(R.layout.wallpaper_item, parent, false));
    }

    @Override
    public void onBindViewHolder(final WallsHolder holder, int position) {
        Animation anim = AnimationUtils.loadAnimation(context, android.R.anim.fade_in);
        HashMap<String, String> jsondata = data.get(position);

        holder.name.setText(jsondata.get(WallpapersActivity.NAME));
        final String wallurl = jsondata.get(WallpapersActivity.WALL);
        holder.wall.startAnimation(anim);
        holder.wall.setTag(wallurl);

        Ion.with(context)
                .load(wallurl)
                .asBitmap()
                .setCallback(new FutureCallback<Bitmap>() {
                    @Override
                    public void onCompleted(Exception e, Bitmap result) {
                        holder.progressBar.setVisibility(View.GONE);
                        if (e != null) {
                            e.printStackTrace();
                        } else if (holder.wall.getTag() != null && holder.wall.getTag().equals(wallurl)) {
                            holder.wall.setImageBitmap(result);
                            if (usePalette) {
                                Palette p;
                                if (mPaletteCache.containsKey(wallurl)) {
                                    p = mPaletteCache.get(wallurl);
                                } else {
                                    p = new Palette.Builder(result).generate();
                                    mPaletteCache.put(wallurl, p);
                                }
                                if (p != null) {
                                    Palette.Swatch wallSwatch = p.getVibrantSwatch();
                                    if (wallSwatch != null) {
                                        holder.titleBg.setBackgroundColor(wallSwatch.getRgb());
                                        holder.titleBg.setAlpha(1);
                                        holder.name.setTextColor(wallSwatch.getTitleTextColor());
                                        holder.name.setAlpha(1);
                                    }
                                }
                            }
                        }
                    }
                });
    }

    @Override
    public int getItemCount() {
        return data.size();
    }

    public class WallsHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {

        public final View view;
        public final ImageView wall;
        public final TextView name;
        public final ProgressBar progressBar;
        public final LinearLayout titleBg;

        WallsHolder(View v) {
            super(v);
            view = v;
            wall = (ImageView) v.findViewById(R.id.wall);
            name = (TextView) v.findViewById(R.id.name);
            progressBar = (ProgressBar) v.findViewById(R.id.progress);
            titleBg = (LinearLayout) v.findViewById(R.id.titlebg);

            view.setOnClickListener(this);
            view.setOnLongClickListener(this);
        }

        @Override
        public void onClick(View v) {
            int index = getLayoutPosition();
            if (mCallback != null)
                mCallback.onClick(this, index, false);
        }

        @Override
        public boolean onLongClick(View v) {
            int index = getLayoutPosition();
            if (mCallback != null)
                mCallback.onClick(this, index, true);
            return false;
        }
    }
}

【问题讨论】:

    标签: java android adapter android-recyclerview palette


    【解决方案1】:

    覆盖onViewRecycled (VH holder) 将图像设置为空。

    像这样:

    public void onViewRecycled (VH holder) {
    
       holder.wall.setImageBitmap(null);
    }
    

    【讨论】:

      【解决方案2】:

      我认为你应该像这样添加占位符:

      Ion.with(context).load("http://example.com/image.png")
          .withBitmap()
          .placeholder(R.drawable.placeholder_image)
          .error(R.drawable.error_image)
          .intoImageView(imageView);
      

      或者先设置默认图片。

      holder.wall.setImageResource(R.drawable.placeholder_image);
      

      【讨论】:

        【解决方案3】:

        顾名思义,RecyclerView 回收视图以优化内存,以便显示前一个视图的内容。由于您是从 Internet 加载图像,因此加载图像所需的时间很少,因此可以观察到先前图像的内容。您可以执行以下操作之一。

        1)在加载实际图像之前从本地资源设置默认图像,最好是小尺寸图像以节省内存。像这样

        //load default image first                 
        holder.wall.setImageResource(R.id.your_default_image_resource);
        //load actual image
        Ion.with(context)
                    .load(wallurl)
            .asBitmap()
            .setCallback(new FutureCallback<Bitmap>() {
                @Override
                public void onCompleted(Exception e, Bitmap result) {
                    holder.progressBar.setVisibility(View.GONE);
                    if (e != null) {
                        e.printStackTrace();
                    } else if (holder.wall.getTag() != null && holder.wall.getTag().equals(wallurl)) {
                        holder.wall.setImageBitmap(result);
                        if (usePalette) {
                            Palette p;
                            if (mPaletteCache.containsKey(wallurl)) {
                                p = mPaletteCache.get(wallurl);
                            } else {
                                p = new Palette.Builder(result).generate();
                                mPaletteCache.put(wallurl, p);
                            }
                            if (p != null) {
                                Palette.Swatch wallSwatch = p.getVibrantSwatch();
                                if (wallSwatch != null) {
                                    holder.titleBg.setBackgroundColor(wallSwatch.getRgb());
                                    holder.titleBg.setAlpha(1);
                                    holder.name.setTextColor(wallSwatch.getTitleTextColor());
                                    holder.name.setAlpha(1);
                                }
                            }
                        }
                    }
                }
            });
        

        2) 在加载图像之前将ImageView 可见性设置为 GONE/INVISIBLE,并在加载图像后再次使其可见。

         //hide the imageview
        holder.wall.setVisibility(View.INVISIBLE);
        Ion.with(context)
                    .load(wallurl)
            .asBitmap()
            .setCallback(new FutureCallback<Bitmap>() {
                @Override
                public void onCompleted(Exception e, Bitmap result) {
                    holder.progressBar.setVisibility(View.GONE);
                    if (e != null) {
                        e.printStackTrace();
                    } else if (holder.wall.getTag() != null && holder.wall.getTag().equals(wallurl)) {
                        //show the imageview and set bitmap
                        holder.wall.setVisibility(View.VISIBLE);
                        holder.wall.setImageBitmap(result);
                        if (usePalette) {
                            Palette p;
                            if (mPaletteCache.containsKey(wallurl)) {
                                p = mPaletteCache.get(wallurl);
                            } else {
                                p = new Palette.Builder(result).generate();
                                mPaletteCache.put(wallurl, p);
                            }
                            if (p != null) {
                                Palette.Swatch wallSwatch = p.getVibrantSwatch();
                                if (wallSwatch != null) {
                                    holder.titleBg.setBackgroundColor(wallSwatch.getRgb());
                                    holder.titleBg.setAlpha(1);
                                    holder.name.setTextColor(wallSwatch.getTitleTextColor());
                                    holder.name.setAlpha(1);
                                }
                            }
                        }
                    }
                }
            });
        

        【讨论】:

        • 第一个选项有效。第二个仍然给了我同样的问题。感谢您的帮助。
        猜你喜欢
        • 1970-01-01
        • 2017-04-12
        • 2010-12-27
        • 2016-07-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-18
        • 2021-01-08
        相关资源
        最近更新 更多