一个优化极点的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点多起来,一气呵成最近的收获与评价,愤慨与忏悔. 四年多前的一 ...
随机推荐
- Dynamics CRM Entity Relationship Many to Many (N:N)
该博客对N:N的关系的查询列出了两种方式,一种RetrieveMultipleRequest,一种Fetch XML ,有谁对N:N关系的查询了解不是很深的可以学习下. http://andreasw ...
- 【mybatis深度历险系列】mybatis中的输入映射和输出映射
在前面的博文中,小编介绍了mybatis的框架原理以及入门程序,还有mybatis中开发到的两种方法,原始开发dao的方法和mapper代理方法,今天博文,我们来继续学习mybatis中的相关知识,随 ...
- Eclipse的Debug调试技巧
作为开发人员,掌握开发环境下的调试技巧十分有必要.我们在编写java程序的过程中,经常会遇到各种莫名其妙的问题,为了检测程序是哪里出现问题,经常需要增加日志,看变量的值,这样调试很麻烦.假设我每天花费 ...
- ROS(indigo) 安装和使用更新版本的Gazebo----3,4,5,6,7 附:中国机器人大赛中型组仿真比赛说明
ROS(indigo) 安装和使用更新版本的Gazebo,本文以7为例. Gazebo7支持更多新的功能,如果使用下面命令安装ROS(indigo): ~$ sudo apt-get install ...
- [extjs5学习笔记]第三十七节 Extjs6预览版都有神马新东西
本文在微信公众号文章地址:微信公众号文章地址 本文地址:http://blog.csdn.net/sushengmiyan/article/details/45190485 [TOC] 在Ext JS ...
- Android使用HttpUrlConnection请求服务器发送数据详解
HttpUrlConnection是java内置的api,在java.net包下,那么,它请求网络同样也有get请求和post请求两种方式.最常用的Http请求无非是get和post,get请求可以获 ...
- C语言中switch case语句可变参实现方法(case 参数 空格...空格 参数 :)
正常情况下,switch case语句是这么写的: : : ... ;break ; default : ... ;break ; } 接下来说一种不常见的,但是对于多参数有很大的帮助的写法: 先给一 ...
- SQL 数据库语言分析总结(一)
SQL语言是被广泛采用的数据库的学习语言,之前在本科的时候已经学习过了,但是后来又忘记了,所以这次简单的总结一下. 分类 交互式sql语言,交互式语言主要是利用一些数据库工具,比如mysql的终端工具 ...
- [shiro学习笔记]第二节 shiro与web融合实现一个简单的授权认证
本文地址:http://blog.csdn.net/sushengmiyan/article/details/39933993 shiro官网:http://shiro.apache.org/ shi ...
- 发现----Android Demo
时间悄悄的走,转眼来实习已经三个月了,三个月的时间,小编慢慢的成长着,从刚开始的电商项目到现在的车段子项目,小编在走过一个又一个项目的同时,走过了一个又一个战胜自己的奇迹,每次遇到一个新的技术点,小编 ...