Android ListView控件
来源:互联网 发布:劳动法教材推荐 知乎 编辑:程序博客网 时间:2024/06/05 03:50
使用ListView来展示数据需要以下三个元素:
1.Android提供的ListView的控件 —— 专门用来展示数据的界面
2.Adapter 适配器 —— 连接ListView和数据的桥梁
3.Data 数据 —— 需要在ListView上展示的数据
在以上三个元素中,Adpater起到了非常重要的作用,它把各种各样的数据抽象为统一的接口供ListView来使用。所以得名“适配器”。
列表的适配器一般分为三种: ArrayAdapter SimpleAdapter SimpleCursorAdapter, 其中以ArrayAdapter最为简单,只能展示一行字。SimpleAdapter有最好的扩充性,可以自定义出各种效果。SimpleCursorAdapter可以认为是SimpleAdapter对数据库的简单结合,可以方面的把数据库的内容以列表的形式展示出来。
一些较为简单的列表(比如ListView的每一项都是用做展示等等),以上的几种Adapter就完全足够用了,但是,如果ListView的某些项用来和用户交互,比如有可以点击的按钮,那么这时候上面的几种Adapter就不能满足我们的需要了,这时候我们必须从BaseAdapter派生出我们自己的Adapter来实现相应的功能。
具体的例子可以看该博客的内容:
点击查看链接
下面重点介绍关于ListView优化的一些知识。
1.使用getView()函数的参数ConvertView
getView方法里也提供了一个参数:convertView,这个参数代表着可以复用的view对象,当然这个对象也可能为空,当它为空的时候,表示该条目view第一次创建,所以我们需要inflate一个view出来,不为空时,直接复用:
@Override public View getView(int position, View convertView, ViewGroup parent) { View view; // 判断convertView的状态,来达到复用效果 if (null == convertView) { //如果convertView为空,则表示第一次显示该条目,需要创建一个view view = View.inflate(MainActivity.this, R.layout.listview_item,null); } else { //否则表示可以复用convertView view = convertView; } // listview_item里只有一个textview TextView tv_item = (TextView) view.findViewById(R.id.tv_item); tv_item.setText(list.get(position)); return view; }
2.使用View Holder模式
上面的例子中,我们可以通过参数convertView来决定是不是需要inflate出来一个ItemView来达到优化的目的,但是呢,拿到convertView之后我们依然需要每次都通过函数findViewById()来查找对应的子控件,如果Layout布局比较复杂,那么这样的操作也会很耗时,所以可以从这里着手来进行进一步的优化:
private static class ViewHolder { private TextView tvHolder; }@Override public View getView(int position, View convertView, ViewGroup parent) { View view; ViewHolder holder; // 判断convertView的状态,来达到复用效果 if (null == convertView) { // 如果convertView为空,则表示第一次显示该条目,需要创建一个view view = View.inflate(MainActivity.this, R.layout.listview_item, null); //新建一个viewholder对象 holder = new ViewHolder(); //将findviewbyID的结果赋值给holder对应的成员变量 holder.tvHolder = (TextView) view.findViewById(R.id.tv_item); // 将holder与view进行绑定 view.setTag(holder); } else { // 否则表示可以复用convertView view = convertView; holder = (ViewHolder) view.getTag(); } // 直接操作holder中的成员变量即可,不需要每次都findViewById holder.tvHolder.setText(list.get(position)); return view; }
这样,每次在新创建ItemView的时候,将View和持有View上的子控件的引用的ViewHolder进行绑定,当getView函数对以前的ItemView进行复用的时候,不需要再次用函数findViewById()进行查找了,而是直接用ViewHolder持有的引用进行操作就可以了,从而达到优化效率的目的。
3.一个优化后的、通用的Adapter的例子:
import android.content.Context;import android.util.SparseArray;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.TextView;import java.util.ArrayList;public abstract class MyAdapter<T> extends BaseAdapter { private ArrayList<T> mData; // 界面上的数据 private int mLayoutRes; // item布局的资源id public MyAdapter() { } public MyAdapter(ArrayList<T> mData, int mLayoutRes) { this.mData = mData; this.mLayoutRes = mLayoutRes; } // 获取数据项的个数 @Override public int getCount() { return mData != null ? mData.size() : 0; } // 获取数据项 @Override public T getItem(int position) { return mData.get(position); } // 获取数据项的索引 @Override public long getItemId(int position) { return position; } // 获取ItemView @Override public View getView(int position, View convertView, ViewGroup parent) { // 拿到holder ViewHolder holder = ViewHolder.bind(parent.getContext(), convertView, parent, mLayoutRes , position); // 数据与view相结合 bindView(holder, getItem(position)); return holder.getItemView(); } // 具体的绑定操作留给用户自己实现 public abstract void bindView(ViewHolder holder, T obj); // 向数据集合中添加一个数据项 public void add(T data) { if (mData == null) { mData = new ArrayList<>(); } mData.add(data); // 刷新界面 notifyDataSetChanged(); } // 特定位置,插入元素 public void add(int position, T data) { if (mData == null) { mData = new ArrayList<>(); } mData.add(position, data); notifyDataSetChanged(); } public void remove(T data) { if (mData != null) { mData.remove(data); } notifyDataSetChanged(); } public void remove(int position) { if (mData != null) { mData.remove(position); } notifyDataSetChanged(); } public void clear() { if (mData != null) { mData.clear(); } notifyDataSetChanged(); } // viewHolder类的实现 public static class ViewHolder { private SparseArray<View> mViews; // 缓存ListView中的Item上的所有子item private View item; // 该viewHolder所持有的item private int position; // item所对应的位置 private Context context; // Context上下文 //构造方法,完成相关初始化 private ViewHolder(Context context, ViewGroup parent, int layoutRes) { mViews = new SparseArray<>(); this.context = context; View convertView = LayoutInflater.from(context).inflate(layoutRes, parent, false); convertView.setTag(this); item = convertView; } //绑定ViewHolder与item public static ViewHolder bind(Context context, View convertView, ViewGroup parent, int layoutRes, int position) { ViewHolder holder; if (convertView == null) { holder = new ViewHolder(context, parent, layoutRes); } else { holder = (ViewHolder) convertView.getTag(); holder.item = convertView; } holder.position = position; return holder; } // 获取Item上的子view,如果有缓存则直接返回,否则需要进行查找并缓存 public <T extends View> T getView(int id) { T t = (T) mViews.get(id); if (t == null) { t = (T) item.findViewById(id); mViews.put(id, t); } return t; } // 获得当前持有的item public View getItemView() { return item; } // 获取索引号 public int getItemPosition() { return position; } // 设置文字 public ViewHolder setText(int id, CharSequence text) { View view = getView(id); if (view instanceof TextView) { ((TextView) view).setText(text); } return this; } // 设置图片 public ViewHolder setImageResource(int id, int drawableRes) { View view = getView(id); if (view instanceof ImageView) { ((ImageView) view).setImageResource(drawableRes); } else { view.setBackgroundResource(drawableRes); } return this; } // 设置监听事件 public ViewHolder setOnClickListener(int id, View.OnClickListener listener) { getView(id).setOnClickListener(listener); return this; } // 设置可见属性 public ViewHolder setVisibility(int id, int visible) { getView(id).setVisibility(visible); return this; } // 设置标签 public ViewHolder setTag(int id, Object obj) { getView(id).setTag(obj); return this; } }}
使用的时候实现BindView函数定义具体的绑定操作:
//Adapter初始化myAdapter1 = new MyAdapter<App>((ArrayList)mData1,R.layout.item_one) { @Override public void bindView(ViewHolder holder, App obj) { holder.setImageResource(R.id.img_icon,obj.getaIcon()); holder.setText(R.id.txt_aname,obj.getaName()); } };
//////////////////////////////////////////////////////////////////////////////
RecyclerView也可以实现ListView的所有功能,但是功能比ListView要强大的多,详见博文
- Android 控件之ListView
- Android 控件 ListView
- android控件12 ListView
- Android控件之ListView
- Android控件之ListView
- android ListView控件
- Android开发--控件ListView
- android控件之ListView
- Android控件之ListView
- [android]控件ListView简介
- android-listview控件
- Android 控件 ListView 用法
- Android 自定义ListView控件
- Android控件ListView
- android 控件 ListView
- Android 控件ListView
- Android控件之ListView
- Android--ListView控件
- JAVA设计模式之工厂模式(简单工厂模式+工厂方法模式)
- qduoj 153 cfenglv的一道简单签到题 (二分+分解因子)
- 工厂模式
- 解决移动端可恨的滚动穿透问题
- c语言上机考试(二)
- Android ListView控件
- Linux进程通信之消息队列的双向通信
- keras的基本用法(五)——图像predict
- MySQl操作整理01
- 常用查找算法
- QT编译链接问题之一
- css之BFC总结
- Error:Execution failed for task ':app:mergeDebugResources'. > Some file crunching failed, see logs f
- SpringBoard相关api记录