Android_ListView适配器
ListView如何优化
- 复用convertView缓存(减少ListView绘制).
- 自定义静态类ViewHolder(减少findViewById次数),通过setTag()、getTag()获取holder实例.
- 使用分页加载.
- 使用软引用WeakReference引用ImageView对象:当item划出屏幕,可以释放对大图片的引用,节省内存,提高效率.
- 另外对图片还可以使用LruCache和三级缓存来优化.
正常使用方式
public class MyAdapter extends BaseAdapter { private LayoutInflater mInflater;
private Context ctx;
private List<String> mDatas; public MyAdapter(Context ctx, List<String> mDatas) {
mInflater = LayoutInflater.from(ctx);
this.ctx = ctx;
this.mDatas = mDatas;
} @Override
public int getCount() {
return mDatas.size(); // 固定
} @Override
public Object getItem(int position) {
return mDatas.get(position); // 固定
} @Override
public long getItemId(int position) {
return position; // 固定
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) { // 复用convertView缓存
convertView = mInflater.inflate(R.layout.item_str, null); // 条目布局
holder = new ViewHolder();
holder.tv = (TextView) convertView.findViewById(R.id.tv); // holder存储控件
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.tv.setText(mDatas.get(position));
return convertView;
} private final class ViewHolder {
TextView tv;
}
}
上述代码大家都很熟悉,基本遇到就是一套,都写烂了,分析一下
- 复写的三个方法都是固定的,很好抽取.
- getView中通过set、get处理ViewHolder对象可以抽取.
- holder中的findViewById可以抽取.
提炼
PART_A:Adapter
package com.catface.cadapter; import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import java.util.List; /** * @desc 使用泛型,接收不同类型的对象 */
public abstract class CAdapter<T> extends BaseAdapter {
protected Context ctx;
protected List<T> datas;
protected LayoutInflater inflater;
private int layoutId; // arg1-3:上下文 | 集合<泛型bean> | 条目布局
public CAdapter(Context ctx, List<T> datas, int layoutId) {
this.ctx = ctx;
this.datas = datas;
this.inflater = LayoutInflater.from(ctx);
this.layoutId = layoutId;
} @Override public int getCount() {
return datas == null ? 0 : datas.size();
} @Override public T getItem(int position) {
return datas == null ? null : datas.get(position);
} @Override public long getItemId(int position) {
return position;
} /** * @desc 1.获取ViewHolder对象(上下文、复用缓存、父布局、条目布局) */
@Override public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = ViewHolder.get(ctx, convertView, parent, layoutId, position);
convert(holder, getItem(position)); // ------>> 暴露抽象方法
return holder.getConvertView(); // 设置结束各个组件,返回ViewHolder对象方便继续设置控件值
} /** * @desc 暴露出去并传入holder与bean:拿着控件设置值 */
public abstract void convert(ViewHolder holder, T t);
}
PART_B:ViewHolder
package com.catface.cadapter; import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.util.Linkify;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.widget.Checkable;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RatingBar;
import android.widget.TextView; /** * @desc 待修复问题: * * 1.CheckBox选中错位(复用convertView所致) √ * a.在Bean中添加isChecked字段 * b.在ListView中用ArrayList数组记录holder中当前选中的CheckBox * * 2.图片显示错位 × * * 3.上拉刷新 + 下拉加载 × */
public class ViewHolder {
private Context ctx; // 上下文
private View convertView; // 复用缓存
private int mLayoutId; // 条目布局
private SparseArray<View> views; // 各组件及对应id(SparseArray代替HashMap,提高效率)
private int position; public ViewHolder(Context ctx, ViewGroup parent, int layoutId, int position) {
this.ctx = ctx;
this.convertView = LayoutInflater.from(ctx).inflate(layoutId, parent, false);
this.mLayoutId = layoutId;
this.views = new SparseArray<View>();
this.position = position;
this.convertView.setTag(this);
} /** * @desc 通过setTag()和getTag()来获取ViewHolder对象 */
public static ViewHolder get(Context ctx, View convertView, ViewGroup parent, int layoutId, int position) {
if (convertView == null) {
return new ViewHolder(ctx, parent, layoutId, position);
} else {
ViewHolder holder = (ViewHolder) convertView.getTag();
holder.position = position;
return holder;
}
} /** * @desc 获取当前holder的position */
public int getPosition() {
return position;
} public int getLayoutId() {
return mLayoutId;
} /** * @desc 通过viewId获取控件 */
@SuppressWarnings("unchecked")
public <T extends View> T getViewByViewId(int viewId) {
View view = views.get(viewId);
if (view == null) {
view = convertView.findViewById(viewId);
views.put(viewId, view);
}
return (T) view;
} public View getConvertView() {
return convertView;
} /************************************************ PS:图片可以使用第三方工具类加载图片 ************************************************/ /** 设置TextView文本 */
public ViewHolder setText(int viewId, String text) {
((TextView) getViewByViewId(viewId)).setText(text);
return this;
} /** 设置TextView颜色 */
public ViewHolder setTextColor(int viewId, int textColor) {
((TextView) getViewByViewId(viewId)).setTextColor(textColor);
return this;
} /** 设置TextView颜色 */
public ViewHolder setTextColorRes(int viewId, int textColorRes) {
((TextView) getViewByViewId(viewId)).setTextColor(ctx.getResources().getColor(textColorRes));
return this;
} /** 设置文本字体 */
public ViewHolder setTypeface(Typeface typeface, int... viewIds) {
for (int viewId : viewIds) {
TextView view = getViewByViewId(viewId);
view.setTypeface(typeface);
view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG);
}
return this;
} /** 设置图片:资源id */
public ViewHolder setImageResource(int viewId, int resId) {
((ImageView) getViewByViewId(viewId)).setImageResource(resId);
return this;
} /** 设置图片:Bitmap */
public ViewHolder setImageBitmap(int viewId, Bitmap bitmap) {
((ImageView) getViewByViewId(viewId)).setImageBitmap(bitmap);
return this;
} /** 设置图片:Drawable */
public ViewHolder setImageDrawable(int viewId, Drawable drawable) {
((ImageView) getViewByViewId(viewId)).setImageDrawable(drawable);
return this;
} /** 设置背景色 */
public ViewHolder setBackgroundColor(int viewId, int color) {
getViewByViewId(viewId).setBackgroundColor(color);
return this;
} /** 设置背景色 */
public ViewHolder setBackgroundRes(int viewId, int backgroundRes) {
getViewByViewId(viewId).setBackgroundResource(backgroundRes);
return this;
} @SuppressLint("NewApi")
public ViewHolder setAlpha(int viewId, float value) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
getViewByViewId(viewId).setAlpha(value);
} else {
// Pre-honeycomb hack to set Alpha value
AlphaAnimation alpha = new AlphaAnimation(value, value);
alpha.setDuration(0);
alpha.setFillAfter(true);
getViewByViewId(viewId).startAnimation(alpha);
}
return this;
} /** 设置可见状态 */
public ViewHolder setVisible(int viewId, boolean visible) {
getViewByViewId(viewId).setVisibility(visible ? View.VISIBLE : View.GONE);
return this;
} public ViewHolder linkify(int viewId) {
TextView view = getViewByViewId(viewId);
Linkify.addLinks(view, Linkify.ALL);
return this;
} /** 设置进度 */
public ViewHolder setProgress(int viewId, int progress) {
((ProgressBar) getViewByViewId(viewId)).setProgress(progress);
return this;
} /** 设置最大进度 */
public ViewHolder setMax(int viewId, int max) {
ProgressBar view = getViewByViewId(viewId);
view.setMax(max);
return this;
} /** 设置进度、最大进度 */
public ViewHolder setProgress(int viewId, int progress, int max) {
ProgressBar view = getViewByViewId(viewId);
view.setMax(max);
view.setProgress(progress);
return this;
} public ViewHolder setRating(int viewId, float rating) {
RatingBar view = getViewByViewId(viewId);
view.setRating(rating);
return this;
} public ViewHolder setRating(int viewId, float rating, int max) {
RatingBar view = getViewByViewId(viewId);
view.setMax(max);
view.setRating(rating);
return this;
} public ViewHolder setTag(int viewId, Object tag) {
View view = getViewByViewId(viewId);
view.setTag(tag);
return this;
} public ViewHolder setTag(int viewId, int key, Object tag) {
View view = getViewByViewId(viewId);
view.setTag(key, tag);
return this;
} public ViewHolder setChecked(int viewId, boolean checked) {
Checkable view = (Checkable) getViewByViewId(viewId);
view.setChecked(checked);
return this;
} /** 设置点击事件 */
public ViewHolder setOnClickListener(int viewId, View.OnClickListener listener) {
getViewByViewId(viewId).setOnClickListener(listener);
return this;
} /** 设置触摸事件 */
public ViewHolder setOnTouchListener(int viewId, View.OnTouchListener listener) {
getViewByViewId(viewId).setOnTouchListener(listener);
return this;
} /** 设置长按事件 */
public ViewHolder setOnLongClickListener(int viewId, View.OnLongClickListener listener) {
getViewByViewId(viewId).setOnLongClickListener(listener);
return this;
}
}
PART_C:多条目的Adapter
- 接口
package com.catface.cadapter; /** * @desc 多条目ListView的Adapter接口 */
public interface IMultiCAdapter<T> {
int getLayoutId(int position, T t); int getViewTypeCount(); int getItemViewType(int postion, T t);
}
- 具体Adapter
package com.catface.cadapter; import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import java.util.List; /** * @desc 多条目的Adapter */
public abstract class MultiCAdapter<T> extends CAdapter<T> { protected IMultiCAdapter<T> mMultiItemTypeSupport; public MultiCAdapter(Context context, List<T> datas, IMultiCAdapter<T> multiItemTypeSupport) {
super(context, datas, -1);
this.mMultiItemTypeSupport = multiItemTypeSupport;
} @Override public int getViewTypeCount() {
if (mMultiItemTypeSupport != null) {
return mMultiItemTypeSupport.getViewTypeCount();
}
return super.getViewTypeCount();
} @Override public int getItemViewType(int position) {
if (mMultiItemTypeSupport != null) {
return mMultiItemTypeSupport.getItemViewType(position, datas.get(position));
}
return super.getItemViewType(position); } @Override public View getView(int position, View convertView, ViewGroup parent) {
if (mMultiItemTypeSupport == null) {
return super.getView(position, convertView, parent);
}
int layoutId = mMultiItemTypeSupport.getLayoutId(position, getItem(position));
ViewHolder viewHolder = ViewHolder.get(ctx, convertView, parent, layoutId, position);
convert(viewHolder, getItem(position));
return viewHolder.getConvertView();
}
}
提炼成果
- 普通条目调用方式
setListAdapter(new CAdapter<Person>(getActivity(), datas, R.layout.item_fragment1) {
@Override
public void convert(ViewHolder viewHolder, Person person) {
viewHolder.setText(R.id.tv_name, person.getName()).setText(R.id.tv_age, person.getAge() + "").setImageResource(R.id.iv_icon, person.getIcon());
}
});
- 带CheckBox等控件,解决其抢占item事件的方法
- 条目布局父控件:
android:descendantFocusability="blocksDescendants"
- CheckBox:
android:focusable="false"
- 条目布局父控件:
setListAdapter(new CAdapter<Person>(getActivity(), datas, R.layout.item_fragment1up) { private List<Integer> points = new ArrayList<Integer>(); @Override
public void convert(final ViewHolder viewHolder, Person person) {
viewHolder.setText(R.id.tv_name, person.getName()).setText(R.id.tv_age, person.getAge() + "").setImageResource(R.id.iv_icon, person.getIcon()); final CheckBox cb = (CheckBox) viewHolder.getViewByViewId(R.id.cb_f1up);
cb.setChecked(false); // 先置为false
if (points.contains(viewHolder.getPosition())) {
cb.setChecked(true);
}
cb.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (cb.isChecked()) {
points.add(viewHolder.getPosition());
} else {
points.remove((Integer) viewHolder.getPosition());
}
}
});
}
Android_ListView适配器的更多相关文章
- Android—万能ListView适配器
ListView是开发中最常用的控件了,但是总是会写重复的代码,浪费时间又没有意义. 最近参考一些资料,发现一个万能ListView适配器,代码量少,节省时间,总结一下分享给大家. 首先有一个自定义的 ...
- 打造android偷懒神器———ListView的万能适配器
如果你去做任何一个项目,我相信你都会跟我有一样的经历,最最普遍的就是列表显示ListView,当然,写N个自定义的适配器也是情理之中.虽说程序员本身就是搬砖,做这些枯燥无味的重复的事情也是理所当然,但 ...
- 打造android偷懒神器———RecyclerView的万能适配器
转载请注明出处谢谢:http://www.cnblogs.com/liushilin/p/5720926.html 很不好意思让大家久等了,本来昨天就应该写这个的,无奈公司昨天任务比较紧,所以没能按时 ...
- ListView和Adapter数据适配器的简单介绍
ListView 显示大量相同格式数据 常用属性: listSelector listView每项在选中.按下等不同状态时的Drawable divider ...
- Android应用项目中BaseAdapter、SimpleAdapter和ArrayAdapter中的三种适配器
一.写在前面: 本次我们来讲解一下Android应用中三个适配器:BaseAdapter.SimpleAdapter和ArrayAdapter.其中常见的是BaseAdapter,也是个人推荐使用的适 ...
- Adapt适配器
为接口提供所有的空实现,让使用者仅仅覆盖需要的部分: 本思想肯定有问题,慢慢考究 frame.addWindowListener(new WindowAdapter() { @Override pub ...
- Android之ListView性能优化——一行代码绑定数据——万能适配器
如下图,加入现在有一个这样的需求图,你会怎么做?作为一个初学者,之前我都是直接用SimpleAdapter结合一个Item的布局来实现的,感觉这样实现起来很方便(基本上一行代码就可以实现),而且也没有 ...
- 【Android自学日记】两种适配器的使用
ArrayAdapter适配器: (1)用于显示基本的文字内容 (2)基本使用过程:新建适配器---创建或加载数据源---适配器加载数据源---视图加载适配器 ArrayAdapter(上下文,当前L ...
- OC编程之道-接口适配之适配器
已有的类与新的接口之间不兼容的问题相当普遍,人们已为它找到了一个解决方案.这个解决方案就是适配器. 1 何为适配器 what 适配器的主要作用是把被适配者的行为传递给管道另一端的客户端. 将一个类的接 ...
随机推荐
- 转 Comparison of Red Hat and Oracle Linux kernel versions and release strings
Originally derived from Red Hat Enterprise Linux (RHEL), Oracle Linux (OL) contains minor difference ...
- swagger demo code
//Application 开启注解 @EnableSwagger2public class Application { public static void main(String[] args) ...
- getopt 学习
https://www.cnblogs.com/qingergege/p/5914218.html
- 数据结构---Java---ArrayList
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess ...
- inventor安装失败怎样卸载安装inventor 2017?
AUTODESK系列软件着实令人头疼,安装失败之后不能完全卸载!!!(比如maya,cad,3dsmax等).有时手动删除注册表重装之后还是会出现各种问题,每个版本的C++Runtime和.NET f ...
- DRF之权限认证频率组建
认证组件 很久很久以前,Web站点只是作为浏览服务器资源(数据)和其他资源的工具,甚少有什么用户交互之类的烦人的事情需要处理,所以,Web站点的开发这根本不关心什么人在什么时候访问了什么资源,不需要记 ...
- 在rails 中使用mysql 出现Mysql::Error: Incorrect string value: 的问题
这是因为你在做数据库的操作中有非英文的问题,之后gem mysql2 处理中文必须要数据库也指定是utf-8 才比较好处理 解决的方法很简单,将数据库每张表都转化成utf-8即可,如果数据库没有什么重 ...
- C/C++中 static 的作用
在C中,有三个作用: 1.修饰全局变量: 作用是隐藏,也就是这个全局变量仅在本文件中可见. 2.修饰局部变量: 作用是扩展变量的生存期,令这个局部变量成为静态的. 3.修饰函数: 作用是隐藏,将此函数 ...
- 《nginx 二》深入理解nginx的各项配置
Nginx应用场景 1.http服务器.Nginx是一个http服务可以独立提供http服务.可以做网页静态服务器. 2.虚拟主机.可以实现在一台服务器虚拟出多个网站,例如个人网站使用的虚拟机. 3. ...
- Graphics绘制类及打印机设置相关
Graphics 有两个多个方法 这里面介绍3个: 1.Graphics.drawString():绘制.画字符串........... e.Graphics.DrawString("新乡市 ...