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 适配器的主要作用是把被适配者的行为传递给管道另一端的客户端. 将一个类的接 ...
随机推荐
- 利用Content-disposition实现无刷新下载图片文件
今天在使用 tinypng.com 这个在线压缩图片的网站时,对其处理完图片后,可以无刷新下载图片感到好奇,于是了解了一下相关实现.无刷新下载可以利用MIME type或者设置Content-disp ...
- Java升级替换java version "1.5.0"
首先进行java安装 http://www.cnblogs.com/someone9/p/8670585.html 2. 然后查看版本信息,仍然是1.5.0 [root@OKC java]# java ...
- Linux执行.sh文件Permission denied
执行sh文件报没有权限: 看下该文件的权限: 缺少执行的权限,直接加上吧: test.sh 权限加上去了,可以执行sh文件了 若用 chmod 4755 filename 可使此程序具有root的权限
- python--upload file into HDFS 加载文件到HDFS
模拟:https://creativedata.atlassian.net/wiki/spaces/SAP/pages/61177860/Python+-+Read+Write+files+from+ ...
- js学习笔记 -- await/ async
await 暂停async function函数,等待Promise处理完成,若Promise 状态为fulfilled,其回调resolve的参数作为await的值,Promise 状态为rejec ...
- 快速排序算法的实现 && 随机生成区间里的数 && O(n)找第k小 && O(nlogk)找前k大
思路:固定一个数,把这个数放到合法的位置,然后左边的数都是比它小,右边的数都是比它大 固定权值选的是第一个数,或者一个随机数 因为固定的是左端点,所以一开始需要在右端点开始,找一个小于权值的数,从左端 ...
- UGUI EventSystem.current.IsPointerOverGameObject(),判断是否进入了UI上
EventSystem.current.IsPointerOverGameObject(); //返回一个布尔值,进入了UI上就返回true,用的时候要 using UnityEngine.Event ...
- ApplicationContextAware的作用
ApplicationContextAware其实我们看到---Aware就知道是干嘛用的了,就是属性注入的, 但是这个ApplicationContextAware的不同地方在于,实现了这个接口的b ...
- accecc2010入门,语文
accecc2010入门 数据库:存放数据并处理的仓库. access2010数据库(扩展名为accdb,改名时不能删扩展名): 1,功能区:代替了菜单栏和工具栏的功能,不用四处查找命令.在窗口下的顶 ...
- EF删除数据
1.方法一,面向对象 using (MyDbContent content = new MyDbContent()) { content.Entry<UserInfo>(model).St ...