首先赞下hyman大神

曾经仅仅是简单的重写个BaseAdapter,将getView方法保持抽象。而ViewHolder没有抽象过。

。。

ViewHolder (用了一个集合+泛型管理存取view)

/**
* author : stone
* email : aa86799@163.com
* time : 15/7/24 14 27
*/
public class StoneViewHolder { private int mPosition;
private View mConvertView;
private SparseArray<View> mViews; //管理listView-item中的view public StoneViewHolder(Context context, int layoutId, int position, ViewGroup parent) {
this.mPosition = position; this.mConvertView = LayoutInflater.from(context).inflate(layoutId, parent, false);
this.mConvertView.setTag(this); this.mViews = new SparseArray<View>();
} public View getConvertView() {
return mConvertView;
} public static StoneViewHolder getInstance(Context context, int layoutId, int position, View
convertView, ViewGroup parent) {
if (convertView == null) {
return new StoneViewHolder(context, layoutId, position, parent);
} else {
StoneViewHolder holder = (StoneViewHolder) convertView.getTag();
holder.mPosition = position; //更新复用的convertView中 position
return holder;
}
} public <T extends View> T getView(int viewId) {
View view = mViews.get(viewId);
if (view == null) {
view = mConvertView.findViewById(viewId);
mViews.put(viewId, view);
}
return (T) view;
} public <T> void setTag(int viewId, T tag) {
getView(viewId).setTag(tag);
} public <T> T getTag(int viewId) {
return (T) getView(viewId).getTag();
} /*------------------------ 设置view属性(以后扩展) --------------------------------*/ public StoneViewHolder setText(int viewId, String text) {
((TextView)getView(viewId)).setText(text);
return this;
} public StoneViewHolder setText(int viewId, int resId) {//R.string.
((TextView)getView(viewId)).setText(resId);
return this;
} public StoneViewHolder setImageBitmap(int viewId, Bitmap bitmap) {
((ImageView)getView(viewId)).setImageBitmap(bitmap);
return this;
} public StoneViewHolder setImageResource(int viewId, int resId) {
((ImageView)getView(viewId)).setImageResource(resId);
return this;
}
}

Adapter

/**
* author : stone
* email : aa86799@163.com
* time : 15/7/24 14 46
*/
public abstract class StoneListAdapter<T> extends BaseAdapter { private List<T> mData;
private Context mContext;
private int mLayoutID; public StoneListAdapter(Context context, int layoutID, List<T> data) {
this.mContext = context;
this.mLayoutID = layoutID;
this.mData = data == null ? new ArrayList<T>() : data;
} @Override
public int getCount() {
return mData.size();
} @Override
public T getItem(int position) {
return mData.get(position);
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
StoneViewHolder holder = StoneViewHolder.getInstance(mContext, mLayoutID, position,
convertView, parent); getView(mContext, holder, position); return holder.getConvertView();
} protected abstract void getView(Context context, StoneViewHolder holder, int position); }

在ListViewActivity中使用

stoneBaseAdapter = new StoneListAdapter<User>(ListViewActivity.this, R.layout.activity_listview_item, mData) {

    @Override
protected void getView(Context context, final StoneViewHolder holder, final int position) {
User user = getItem(position); holder.setText(R.id.tv_id, user.getId()).setText(R.id.tv_name, user.getName())
.setText(R.id.tv_age, user.getAge() + ""); holder.getView(R.id.btn_test).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) { }
}); }
};

关于Adapter中View抢焦点:

假设 listView.setOnItemClickListener(listener);   且item中的  button.setOnClickListener(listener);

无论怎么点击,button会一直被触发...

仅仅须要在item的root-layout中 加入 一个属性:   android:descendantFocusability="blocksDescendants"

关于item-view复用后。显示混乱:

有时条目过多,滑动到下一屏数据时。有些view复用后,view的状态(比方CheckBox的选种状态。ImageView的图片反复出现)会变乱。

一般处理呢。须要有一个机制,来管理一种相应关系: 当前position相应哪种状态

比方说checkBox选中状态混乱:

class MyAdapter extends StoneListAdapter<User> {
private SparseBooleanArray mCheckStateArray; public MyAdapter(Context context, int layoutID, List data) {
super(context, layoutID, data);
this.mCheckStateArray = new SparseBooleanArray();
} public void setChecked(int position, boolean isChecked) {
mCheckStateArray.put(position, isChecked);
} public boolean isChecked(int position) {
return mCheckStateArray.get(position);
} @Override
protected void getView(Context context, final StoneViewHolder holder, final int position) { CheckBox cb = holder.getView(R.id.cb_check);
cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
setChecked(position, isChecked);//记录状态。防缓存显示
}
});
cb.setChecked(isChecked(position));
}
}

关于SparseArray

SparseArray 内部实现是Array数组。当长度不够时,会调用System.arrayCopy

        内部有 keys和values两个数组。

put(key, value); 二分法查找key应该存放的位置  由于key是Integer类型

        put、get时 两个数组都是操作的同一个位置上的数据





    SparseArray 用于替代形如  HashMap<Integer, Object>

    SparseBooleanArray 用于替代形如  HashMap<Integer, Boolean>

    SparseIntArray 用于替代形如  HashMap<Integer, Integer>

    SparseLongArray 用于替代形如  HashMap<Integer, Long>

support.v4.util.SparseArrayCompat 提供了v4包相应平台的 SparseArray实现

Android BaseAdapter和ViewHolder 优化 解决ListView的item抢焦点问题和item错乱问题的更多相关文章

  1. Android中利用ViewHolder优化自定义Adapter的典型写法

    利用ViewHolder优化自定义Adapter的典型写法 最近写Adapter写得多了,慢慢就熟悉了. 用ViewHolder,主要是进行一些性能优化,减少一些不必要的重复操作.(WXD同学教我的. ...

  2. android Baseadapter 和 ViewHolder的使用

    昨晚学习了徐大神的关于BaseAdapter的讲解,让我受益匪浅特来博客留下印记 说到baseadapter大家一定都不陌生,下面这张图就展示了数据.listview.baseadapter 之间的关 ...

  3. 解决ListView在界面只显示一个item

    ListView只显示一条都是scrollview嵌套listView造成的,将listView的高度设置为固定高度之后,三个条目虽然都完全显示.但是这个地方是动态显示的,不能写死.故采用遍历各个子条 ...

  4. Ubuntu中Android SDK Manager无法更新解决办法

    Ubuntu中Android SDK Manager无法更新解决办法http://hi.baidu.com/petercao2008/item/d7a64441f04668e81e19bc1a

  5. Android内存优化解决 资料和总结的经验分享

    在前公司做一个图片处理的应用时, 项目交付的时候,客户的手机在运行应用的时候,一直在崩溃,而这个异常就是OutOfMemory的错误,简称为OOM, 搞得我们也是极其的崩溃,最后 ,我们是通过网上搜集 ...

  6. [Android]对BaseAdapter中ViewHolder编写简化

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/3642849.html 在Android项目中,经常都会用到Li ...

  7. android 自定义adapter和线程结合 + ListView中按钮滑动后状态丢失解决办法

    adapter+线程 1.很多时候自定义adapter的数据都是来源于服务器的,所以在获取服务器的时候就需要异步获取,这里就需要开线程了(线程池)去获取服务器的数据了.但这样有的时候adapter的中 ...

  8. [Android]对BaseAdapter中ViewHolder编写简化(转)

    来自博客:http://www.cnblogs.com/tiantianbyconan/p/3642849.html 在Android项目中,经常都会用到ListView这个控件,而相应的Adapte ...

  9. Android开发之漫漫长途 XIV——ListView

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

随机推荐

  1. Java基础知识(二)

    一.基本概念 1. Java程序初始化的顺序是怎么样的 2. Java和C++的区别 3. 反射 先看一个知乎回答 什么是反射 主要用途 获得Class对象 4. 注解 什么是注解 为什么要用注解 基 ...

  2. Visual Studio 2017创建XAML文件

    Visual Studio 2017创建XAML文件   在Visual Stuido 2015中,在已经创建好的项目中添加XAML文件,只要右击项目,单击“添加”|“新建项”命令,然后从“添加新项” ...

  3. 【BZOJ 2878】 2878: [Noi2012]迷失游乐园 (环套树、树形概率DP)

    2878: [Noi2012]迷失游乐园 Description 放假了,小Z觉得呆在家里特别无聊,于是决定一个人去游乐园玩.进入游乐园后,小Z看了看游乐园的地图,发现可以将游乐园抽象成有n个景点.m ...

  4. PMP CMM

    CMM和PMP是两个不同的概念域,是用来解决不同问题的.我们所说的CMM,准确的说应该是叫做能力成熟度模型,北京猴子说的软件能力成熟度模型实际上应该称为SW-CMM,是CMM的一个子集.PMP可以看做 ...

  5. BZOJ 1115 [POI2009]石子游戏Kam(阶梯博弈)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1115 [题目大意] 有N堆石子,除了第一堆外,每堆石子个数都不少于前一堆的石子个数. ...

  6. Generator函数(一)

    Generator函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同.对于这个函数有多种理解.从语法上来理解,可以将它理解成一个状态机,封装了多个内部状态.内部的不同状态是通过yiel ...

  7. [转]spring的ParameterMethodNameResolver

    例1: ParameterMethodNameResolver,这个可以根据请求的参数来确定一个需要调用的方法.例如,http://www.sf.net/index.view?testParam=te ...

  8. WPF的UI虚拟化

    许多时候,我们的界面上会呈现大量的数据,如包含数千条记录的表格或包含数百张照片的相册.由于呈现UI是一件开销比较大的动作,一次性呈现数百张照片就目前的电脑性能来说是需要占用大量内存和时间的.因此需要对 ...

  9. What happens when a SQL Query runs?

    Posted by Padma Chitturi in Uncategorized. Leave a Comment Hi Folks, It has been such a long time th ...

  10. Java8新语言特性

    Java8简明指南 欢迎来到Java8简明指南.本教程将一步一步指导你通过所有新语言特性.由短而简单的代码示例,带你了解如何使用默认接口方法,lambda表达式,方法引用和可重复注解.本文的最后你会熟 ...