1.发生混乱的原因

借用别人的图来解释一下:1.如上图第一屏的7条数据,也就是会产生7条数据和7个新的布局,2.当屏幕滑动第一条数据消失,复用机制就会发生了,先把item1放到recycler中,等待屏幕底部数据出现,3当item8出现时,就会复用item1的布局和数据,。
也可以这样
public View getView(int position, View convertView, ViewGroup viewGroup) {
System.out.println("getView" + position + " "+ convertView);
}可以发现刚创建时前7个item返回的convertment全是null,第8个item出现,conertView就不为空了,这就对应了if(convertView == null){
//创建布局
}else{
//取tag对应的布局
}2.由于布局会产生复用,保证了内存的消耗很小,但是也会常常发生混乱的情况解决办法:a.利用HashMap()
private class ViewHolder{
private TextView tv_name;
private TextView tv_age;
private TextView tv_des;
private ImageView iv_icon;
public ViewHolder(View convertView){
iv_icon = convertView.findViewById(R.id.iv_icon);
tv_age = convertView.findViewById(R.id.tv_age);
tv_name = convertView.findViewById(R.id.tv_name);
tv_des = convertView.findViewById(R.id.tv_des);
}
}
//getView()中直接从HashMap去取,HashMap
//的对应关系,布局混乱就会避免 private HashMap<Integer , View>lamp =new HashMap<>();
@Override
public View getView(int position, View convertView, ViewGroup viewGroup) {
System.out.println("getView" + position + " "+ convertView);
ViewHolder holder ;
if (lamp.get(position)== null){
convertView = getLayoutInflater().inflate(R.layout.item_first_fragment,null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
lamp.put(position , convertView);
}else {
convertView = lamp.get(position);
holder = (ViewHolder) convertView.getTag();
}
holder.tv_des.setText(mData.get(position).getDes());
holder.tv_name.setText(mData.get(position).getName());
holder.tv_age.setText(String.valueOf(mData.get(position).getAge()));
if (position == 1 || position == 3){
holder.iv_icon.setImageResource(R.drawable.play);
}else {
holder.iv_icon.setVisibility(View.GONE);
}
return convertView;
}b,判断语句一定一定一定(三遍)要有if对应的else
例如
if (position == 1 || position == 3){
holder.iv_icon.setImageResource(R.drawable.play);
}else {
holder.iv_icon.setVisibility(View.GONE);
}c.大牛封装的CommonAdapter,亲测可用,还不用写ViewHolder了,方便public abstract class CommonAdapter extends BaseAdapter {
@Override
public int getCount() {
return getDataCount();
}
@Override
public Object getItem(int i) {
return i;
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int position, View view, ViewGroup parent) {
if (null==view){
view = getContentView(position,view,parent);//view为空就去创建view
HashMap<Integer , View>views = new HashMap<>();//用hashMap存储view,这样就有了对应关系,每个position对应一个view
view.setTag(views);
}
bindData(position , view);
return view;
}
public <T>T getViewById(Class<T> c , View convertView , int resId){
HashMap<Integer , View> views = (HashMap<Integer, View>) convertView.getTag();
if (null == views){
views = new HashMap<>();
}
View view = views.get(resId);
if (null == view){
view = convertView.findViewById(resId);
views.put(resId,view);
}
convertView.setTag(views);
return c.cast(view);
}
public <T> T getViewById(View convertView , int resId){
return (T)getViewById(View.class , convertView , resId);
}
public abstract View getContentView(int position , View convertView , ViewGroup parent);
public abstract int getDataCount();
public abstract void bindData(int position , View convertView);
}
d.解决图片混乱的问题
原因:如果网络加载图片,本身item的图片还未来的及加载,就直接复用了其他item的图片了
// 给 ImageView 设置一个 tag
holder.img.setTag(imgUrl);
// 预设一个图片
holder.img.setImageResource(R.drawable.ic_launcher);
// 通过 tag 来防止图片错位
if (imageView.getTag() != null && imageView.getTag().equals(imageUrl)) {
imageView.setImageBitmap(result);
}
本文详细解析了RecyclerView中布局复用的原理及其可能导致的数据混乱问题,并提供了多种实用的解决方案,包括使用ViewHolder模式、判断语句优化、自定义适配器以及解决图片加载错乱的方法。
5948

被折叠的 条评论
为什么被折叠?



