一个优化极点的ViewHolder
代码中有注释:
使用方法:
1.可以在listview,gridview,stageView直接继承LazyAdapter使用
2.下面有Demo 代码
ViewHolder代码:
import android.content.Context; import android.util.SparseArray; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; /** * holder处理的事情 * 1.处理item的每个点击事件,具体业务由adapter来实现 * 2.封装每个item的单一数据 * * @param <T> T为当前item的单一数据 */ public class SmartViewHolder<T> implements View.OnClickListener { //封装item的所有view private final SparseArray<View> mViews = new SparseArray<View>(); private final SparseArray<Object> notifyFlags = new SparseArray<Object>(); //当前item的数据 private T currentData; private final LazyAdapter<T> adapter; private View mConvertView; private SmartViewHolder(Context context, ViewGroup parent, int layoutId, T currentData, LazyAdapter<T> adapter) { mConvertView = LayoutInflater.from(context).inflate(layoutId, parent, false); mConvertView.setTag(this); this.currentData = currentData; this.adapter = adapter; } public T getCurrentData() { return currentData; } public void setCurrentData(T currentData) { this.currentData = currentData; } /** * SmartViewHolder 单例操作 * * @param context * @param convertView * @param currentData * @param parent * @param layoutId * @return holder instance */ public static <T> SmartViewHolder<T> obtainHolder(Context context, View convertView, T currentData, ViewGroup parent, int layoutId, LazyAdapter<T> adapter) { if (convertView == null) { return new SmartViewHolder<T>(context, parent, layoutId, currentData, adapter); } SmartViewHolder<T> holder = (SmartViewHolder<T>) convertView.getTag(); holder.currentData = currentData; return holder; } /** * 获取item指定view * * @param viewId view's id */ public <V extends View> V getView(int viewId) { return getView(viewId, false); } /** * 获取item指定view * * @param viewId view's id * @param hasClickEvent 如果该view不需要click事件 false */ public <V extends View> V getView(int viewId, boolean hasClickEvent) { View view = mViews.get(viewId); if (view == null) { view = mConvertView.findViewById(viewId); mViews.put(viewId, view); if (hasClickEvent) { view.setOnClickListener(this); } } return (V) view; } /** * 添加需要click的view * @param views 可变参数,view's id */ public void requestClickEvent(int... views) { for (int item : views) { getView(item, true); } } @Override public void onClick(View v) { //回调holder指定view的click事件 transferClickEvent(v, currentData); } /** * 回调holder的点击事件,具体业务实现在adapter * @param view * @param currentData */ private void transferClickEvent(View view, T currentData) { adapter.handleClick(this, view, currentData); } /** * @return rootView */ public View getConvertView() { return mConvertView; } /** * 1.数据显示完成后,用holder记住view正在显示的数据, * 下次notify时,如果数据没有变化,则不用再次显示 * 2.如果该view的数据发生变化,则需要调用updateShowingData()更新变化的数据 * * @param view * @param data * @return */ public boolean showingDataChanged(View view, Object data) { return !(notifyFlags.get(view.getId()) != null && notifyFlags.get(view.getId()).equals(data)); } /** * 如果该view的数据发生变化,则需要调用该方法来更新变化的数据 * * @param view * @param data */ public void updateShowingData(View view, Object data) { notifyFlags.put(view.getId(), data); } public Object getShowingData(View view) { return notifyFlags.get(view.getId()); } }
adapter代码:添加了增删的方法
package com.smart_holder_lib; import android.content.Context; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; /** * @param <T> T为当前Item数据 * @author Relice */ public abstract class LazyAdapter<T> extends BaseAdapter { private static final String TAG = LazyAdapter.class.getSimpleName(); protected Context mContext; //设置数据 private final List<T> dataSet = new ArrayList<T>(); //被选中要删除的数据 public final HashSet<T> removeDataSet = new HashSet<T>(); // adapter的item布局 private int mItemLayoutId; //checkBox选中的数据 private T removeData; private List<T> datas;//传过来的数据 /** * 调用该方法你需要传入以下数据 * @param context * @param datas 列表需要显示的数据集合 * @param mItemLayoutId item布局 */ public LazyAdapter(Context context, List<T> datas, int mItemLayoutId) { this.mContext = context; this.datas = datas; this.mItemLayoutId = mItemLayoutId; setDatas(datas); } @Override public int getCount() { return dataSet.size(); } @Override public T getItem(int position) { if (position > -1 && position < dataSet.size()) { return dataSet.get(position); } return null; } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { T currentData = getItem(position); //holder处理的事情 //1.处理item的每个点击事件 //2.封装每个item的单一数据 SmartViewHolder<T> viewHolder = SmartViewHolder.obtainHolder(mContext, convertView, currentData, parent, mItemLayoutId, this); //显示holder填好数据的item -- show UI showDataInItemView(viewHolder, currentData); return viewHolder.getConvertView(); } /** * 覆盖此方法来显示UI * * @param viewHolder holder ,使用他来操作view的一些逻辑事件 * @param currentData 当前item的数据 */ protected abstract void showDataInItemView(SmartViewHolder<T> viewHolder, T currentData); /** * 覆盖此方法来处理点击事件,如果当前item没有任何点击事件,直接空实现即可 * * @param convertView item view * @param view clicked view * @param currentData data of current item */ protected abstract void handleClick(SmartViewHolder<T> convertView, View view, T currentData); /** * 重置所有数据 */ public void setDatas(List<T> datas) { if (datas == null) { return; } Log.d(TAG, "setDatas " + datas.size()); this.dataSet.clear(); this.dataSet.addAll(datas); notifyDataSetChanged(); } /** * 重置单个数据 */ public void setData(T data) { if (data == null) { return; } dataSet.clear(); dataSet.add(data); } /** * 加载更多时-添加数据 * * @param datas * @param filterData */ public void addDatas(List<T> datas, boolean filterData) { if (datas == null) { return; } if (filterData) { this.dataSet.removeAll(datas); } this.dataSet.addAll(datas); notifyDataSetChanged(); } /** * 加载更多时-添加数据 * * @param datas */ public void addDatas(List<T> datas) { addDatas(datas, false); } /** * 加载更多时-添加数据 * * @param data */ public void addData(T data) { if (data == null || dataSet.contains(data)) { return; } dataSet.add(data); notifyDataSetChanged(); } /** * 添加要删除的数据--批量添加 * * @param removeData */ public void addRemoveData(T removeData) { if (removeData != null) { removeDataSet.add(removeData); } } /** * 移除被添加的数据 * * @param removeData */ public void removeAddedData(T removeData) { if (removeData != null) { removeDataSet.remove(removeData); } } /** * 批量删除添被加了数据, * 一般用于activity回调adapter刷新数据 */ public void removeAllData() { if (removeDataSet == null) { return; } for (Iterator it = removeDataSet.iterator(); it.hasNext(); ) { T next = (T) it.next(); if (next == null) { continue; } this.dataSet.remove(next); this.datas.remove(next);//TODO 删除传过来的数据 it.remove(); } notifyDataSetChanged(); } }
Demo使用:
下面只给了主要代码;部分helper,utils 工具类没贴出来
import android.app.Activity; import android.content.Intent; import android.text.TextUtils; import android.view.View; import android.widget.CheckBox; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import com.smart_holder_lib.LazyAdapter; import com.smart_holder_lib.SmartViewHolder; import java.util.List; /** * 我的关注-品牌列表 * 优化处理 * * @author Relice */ public class MyXiuNewCollectionBrandAdapter extends LazyAdapter<BrandInfo> { private Activity activity; private Utils util; private int index; public void setIndex(int index) { this.index = index; } public MyXiuNewCollectionBrandAdapter(Activity activity, List<BrandInfo> list, int index, int layoutId) { super(activity, list, layoutId); this.activity = activity; util = Utils.getInstance(); this.index = index; } @Override protected void showDataInItemView(SmartViewHolder<BrandInfo> holder, BrandInfo brandInfo) { ImageView my_collection_brand_iv = holder.getView(R.id.my_collection_brand_iv, false); TextView my_collection_brand_tv = holder.getView(R.id.my_collection_brand_tv, false); TextView my_collection_brandname = holder.getView(R.id.my_collection_brandname, false); TextView my_collection_brandchosen = holder.getView(R.id.my_collection_brandchosen, false);//精选卖场TV CheckBox my_collection_delbranditem_cb = holder.getView(R.id.my_collection_delbranditem_cb, true);//勾选删除 RelativeLayout my_collection_right_layouttop = holder.getView(R.id.my_collection_right_layouttop, true);//新品上架 RelativeLayout my_collection_right_layoutbuttom = holder.getView(R.id.my_collection_right_layoutbuttom, true);//精选卖场 LinearLayout collect_brand_logo_layout = holder.getView(R.id.collect_brand_logo_layout, true);//品牌logo卖场 //是否需要删除 my_collection_delbranditem_cb.setChecked(brandInfo.isDelItem()); //品牌图片 final boolean hasImage = !TextUtils.isEmpty(brandInfo.getBrandImg()); if (hasImage) { //数据显示完成后,用holder记住view正在显示的数据,下次notify时,如果数据没有变化,则不用再次显示 if (holder.showingDataChanged(my_collection_brand_iv, brandInfo.getBrandImg())) { util.loadBrandCollectImage(activity, my_collection_brand_iv, brandInfo.getBrandImg()); holder.updateShowingData(my_collection_brand_iv, brandInfo.getBrandImg()); SHelper.vis(my_collection_brand_iv); SHelper.gone(my_collection_brand_tv); } } else {//没有图片显示品牌名 SHelper.vis(my_collection_brand_tv); SHelper.gone(my_collection_brand_iv); my_collection_brand_tv.setText(brandInfo.getBrandName()); } //品牌名 String brandName = brandInfo.getBrandName(); if (holder.showingDataChanged(my_collection_brandname, brandName)) { // 数据显示完成后,用holder记住view正在显示的数据,下次notify时,如果数据没有变化,则不用再次显示 my_collection_brandname.setText(brandName); holder.updateShowingData(my_collection_brandname, brandName); } else { // SLog.dd("复用数据.."); } //编辑/完成 if (index == 1) { SHelper.vis(my_collection_delbranditem_cb); } else { SHelper.gone(my_collection_delbranditem_cb); } //处理编辑状态点击 handleEdietStatus(my_collection_delbranditem_cb, my_collection_right_layoutbuttom, my_collection_right_layouttop, collect_brand_logo_layout); //卖场活动是否结束 final int topicCnt = brandInfo.getTopicCnt(); if (topicCnt == 0) { my_collection_right_layoutbuttom.setEnabled(false); my_collection_brandchosen.setTextColor(activity.getResources().getColor(R.color.xiu_grey)); } else { my_collection_brandchosen.setTextColor(activity.getResources().getColor(R.color.xiu_black)); // my_collection_right_layoutbuttom.setEnabled(true); } } private void handleEdietStatus(CheckBox cb, View... view) { boolean clickAble = true; if (cb != null && cb.getVisibility() == View.VISIBLE) clickAble = false; else clickAble = true; for (int i = 0; i < view.length; i++) { view[i].setEnabled(clickAble); } } @Override protected void handleClick(SmartViewHolder<BrandInfo> convertView, View view, BrandInfo brandInfo) { switch (view.getId()) { case R.id.my_collection_right_layouttop://新品上架 activity.startActivity(new Intent(activity, BrandGoodsListActivity.class).putExtra("brand_id", brandInfo.getBrandId() + "").putExtra("brand_name", brandInfo.getBrandName()).putExtra("brand_img", brandInfo.getBrandImg()).putExtra("brand_tag", 3).putExtra("goodsFrom", "UC0040")); break; case R.id.my_collection_right_layoutbuttom://精选卖场 final int topicCnt = brandInfo.getTopicCnt(); if (topicCnt == 1) { activity.startActivity(new Intent(activity, GoodsListActivity.class). putExtra("activity_id", brandInfo.getActivityId()).putExtra("activity_name", brandInfo.getBrandName()).putExtra("activity_img", brandInfo.getBrandImg()). putExtra("goodsFrom", "UC0040")); } else { activity.startActivity(new Intent(activity, SelectStoresActivity.class). putExtra("brand_name", brandInfo.getBrandName()).putExtra("brand_id", brandInfo.getBrandId()).putExtra("goodsFrom", "UC0040")); } break; case R.id.collect_brand_logo_layout: //品牌logo卖场 activity.startActivity(new Intent(activity, BrandGoodsListActivity.class).putExtra("brand_id", brandInfo.getBrandId() + "").putExtra("brand_name", brandInfo.getBrandName()).putExtra("brand_img", brandInfo.getBrandImg()).putExtra("goodsFrom", "UC0040")); break; case R.id.my_collection_delbranditem_cb: //勾选要删除的品牌 CheckBox cb = (CheckBox) view.findViewById(R.id.my_collection_delbranditem_cb); boolean checked = cb.isChecked(); if (checked) { brandInfo.setIsDelItem(true); addRemoveData(brandInfo);//添加删除 } else { brandInfo.setIsDelItem(false); removeAddedData(brandInfo);//取消删除 } break; } } }
一个优化极点的ViewHolder的更多相关文章
- ListView性能优化——convertView&viewHolder
ListView优化大致从以下几个角度:1.复用已经生成的convertView:2.添加viewHolder类:3.缓存数据(图片缓存):4.分页加载. 具体方案: 1.如果自定义适配器,那么在ge ...
- ListView优化的时候ViewHolder的简洁写法
在ListVIew做复用优化的时候,经常会写ViewHolder,还需要很麻烦的去findview,我最讨厌写一堆的这样代码了,今天看到了一个极简的写法,很好用,很简洁啊!!! public stat ...
- MySQL order by的一个优化思路
最近遇到一条SQL线上执行超过5s,这显然无法忍受了,必须要优化了. 首先看眼库表结构和SQL语句. CREATE TABLE `xxxxx` ( `id` ) NOT NULL AUTO_INCRE ...
- 《转》Unity3D研究院之UGUI一个优化效率小技巧
无意间发现了一个小技巧.如下图所示,可以发现UGUI的Image组件的RaycastTarget勾选以后会消耗一些效率,为了节省效率就不要勾选它了,不仅Image组件Text组件也有这样的问题. 一般 ...
- Unity教程之-UGUI一个优化效率小技巧
无意间发现了一个小技巧.如下图所示,可以发现UGUI的Image组件的RaycastTarget勾选以后会消耗一些效率,为了节省效率就不要勾选它了,不仅Image组件Text组件也有这样的问题. 一般 ...
- 大流量网站性能优化:一步一步打造一个适合自己的BigRender插件
BigRender 当一个网站越来越庞大,加载速度越来越慢的时候,开发者们不得不对其进行优化,谁愿意访问一个需要等待 10 秒,20 秒才能出现的网页呢? 常见的也是相对简单易行的一个优化方案是 图片 ...
- VS编译器优化诱发一个的Bug
VS编译器优化诱发一个的Bug Bug的背景 我正在把某个C++下的驱动程序移植到C下,前几天发生了一个比较诡异的问题. 驱动程序有一个bug,但是这个bug只能 Win32 Release 版本下的 ...
- Android数据适配器(Adapter)优化:使用高效的ViewHolder
原文链接:http://stackvoid.com/using-adapter-in-efficiency-way/ 在使用Listview或GridView的时候,往往须要自己定义数据适配器.一般都 ...
- 从Linux 2.6.8内核的一个TSO/NAT bug引出的网络问题排查观点(附一个skb的优化点)
梦中没有错与对,梦中没有恨和悔...最好闭上你的嘴.这样才算可爱...我不会说:这不公道,我不能接受.我会用朴素的文字记录点点滴滴,早上4点多起来,一气呵成最近的收获与评价,愤慨与忏悔. 四年多前的一 ...
随机推荐
- Python 元组内置函数
Python元组包含了以下内置函数 序号 方法及描述 1 cmp(tuple1, tuple2)比较两个元组元素. 2 len(tuple)计算元组元素个数. 3 max(tuple)返回元组中元素最 ...
- ZooKeeper之(四)配置与命令
4.1 配置文件 ZooKeeper安装好之后,在安装目录的conf文件夹下可以找到一个名为"zoo_sample.cfg"的文件,是ZooKeeper配置文件的模板. ZooKe ...
- ubuntu ssh 防止登陆断开
client 端: echo -e '\nServerAliveInterval 30' >> ~/.ssh/ssh_config server 端: echo -e '\nClientA ...
- Lucene查询结果高亮
检索结果高亮 实现效果: 核心代码 package ucas.ir.lucene; import java.io.File; import java.io.IOException; import ja ...
- Python 表示无穷大的数
我之前只知道设置初始值0.今天偶然在Python算法书上看到这个片段,从100个随机数里面找2个最靠近的自然数(不相等): from random import randrange seq = [ra ...
- RE模块错误已解决.
下面这个错误是由于在正则[...]的内部,减号'-'是一个有特殊含义的字符(代表字符范围) 所以如果需要在[...]内匹配减号'-',需要用反斜杠'\'转义. >>> import ...
- springMVC源码分析--动态样式ThemeResolver(一)
Spring MVC中通过ThemeSource接口来提供对动态更换样式的支持,并提供了ResourceBundleThemeSource这个具体实现类来提供通过properties配置文件对them ...
- springmvc文件上传和拦截器
文件上传 用到这两个包 配置视图解析器:springmvc配置文件配置 <!-- id必须要是"multipartResolver" --> <bean id=& ...
- Effective C++ ——实现
条款26:尽可能延后变量定义式的出现时间 当你定义一个变量的时候就要保证这个变量能够在程序中使用到,不要定义无意义的变量,这样就要求我们最好是在变量使用到的时候才做定义,因为如果一个变量定义了却不使用 ...
- 今天我点亮了CSDN博客专家殊荣
很久以前,看着csdn博客学习第一篇博客时,我依旧记得,是一个名叫蒋老夫子的博客专家,文章写的非常认真.内心很崇拜.在想,若干年后,在哪个地方?以什么样的一种状态,也得到此殊荣,华为有句口号,叫勇敢做 ...