ViewHolder模式超简洁写法,很cool!

我们平时怎么写Adapter中的ViewHolder,一般都是按以下的方式写的吧:

@Override
        public View getView(final int position, View convertView, ViewGroup container) {
            // TODO Auto-generated method stub
            final ViewHolder holder;
            final BannerItem item = getItem(position);
            if (convertView == null) {
                holder = new ViewHolder();
                convertView = LayoutInflater.from(container.getContext()).inflate(R.layout.account_banner, container, false);
                holder.mImageView = (ImageView)convertView.findViewById(R.id.iv_banner);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
            if (mImageLoader != null) {
                mImageLoader.loadImage(holder.mImageView, item.getUrl());
            }
            holder.mImageView.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                }
            });
            return convertView;
        }

private class ViewHolder {
            ImageView mImageView = null;
        }

或者就是直接在getView里面新new一个View,与上面的inflate方式大同小异。

这么写一次还行,但问题是总有很多很多的ViewAdapter要这么写,每次都repeat,repeat,repeat 累啊。 所以,有这么一种简洁的写法分享给大家,先声明,从国外网站上看的,不是自己原创的,但确实很喜欢这个简洁的设计。

public class ViewHolder {
    // I added a generic return type to reduce the casting noise in client code
    @SuppressWarnings("unchecked")
    public static <T extends View> T get(View view, int id) {
        SparseArray<View> viewHolder = (SparseArray<View>) view.getTag();
        if (viewHolder == null) {
            viewHolder = new SparseArray<View>();
            view.setTag(viewHolder);
        }
        View childView = viewHolder.get(id);
        if (childView == null) {
            childView = view.findViewById(id);
            viewHolder.put(id, childView);
        }
        return (T) childView;
    }
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
 
    if (convertView == null) {
        convertView = LayoutInflater.from(context)
          .inflate(R.layout.banana_phone, parent, false);
    }
 
    ImageView bananaView = ViewHolder.get(convertView, R.id.banana);
    TextView phoneView = ViewHolder.get(convertView, R.id.phone);
 
    BananaPhone bananaPhone = getItem(position);
    phoneView.setText(bananaPhone.getPhone());
    bananaView.setImageResource(bananaPhone.getBanana());
 
    return convertView;
}

分享了一个github上的开源项目小工具,更cool更简洁! 核心同样是使用SparseArray存储id+view,但更巧妙的是使用Builder模式进一步封装了常用的控件方法,进一步简化了代码~
地址是base-adapter-helper

其实这种写法本质和ViewHolder Partten没有什么不同,ViewHolder Partten是把一个自定义类绑定到一个view,这种是把SparseArray绑定到一个view,虽然SparseArray 初始化会分配10长度的地址,理论上貌似浪费了内存,理论上插入和删除操作也是有时间损耗的,但是这些都在允许范围内。

比如base-adapter-helper 作者也说了他做了大量测试,这种损耗微乎其微。

再次,万一万一因特殊情况发现了有性能瓶颈,到时候再优化就可以了,但是绝大多数场合都是可以使用的,大量简化你的开发,加快开发速度,代码少了,出错的几率就小了,维护的成本也小了~好处还是大大的。

文章目录
|