摆脱ViewHolder,一种无需ViewHolder的高效ListView写法
来源:互联网 发布:淘宝怎样发布二手宝贝? 编辑:程序博客网 时间:2024/06/05 05:06
使用ListView来展示列表数据,基本上是每个Android猿必须掌握的技能,而ListView的基本优化技巧,基本也烂大街了,无非是复用convertView对象还有使用ViewHolder来缓存Item中各个子View的引用。
最近看到一篇文章,描述了一种非主流的高效的ListView写法,无需创建ViewHolder类和holder对象,不用setTag()和getTag(),感觉效率更高。
原文见
http://www.bignerdranch.com/blog/customizing-android-listview-rows-subclassing/
原文作者通过创建RelativeLayout子类(这里ListView各item的布局的根布局是RelativeLayout,根据实际情况而定)来封装所有自定义操作,如findViewById各个子View,填充数据等。
原文作者不喜欢ViewHolder的原因
- ViewHolder模式会在Adapter的getView(…)方法中干了太多事。
- ViewHolder类太过公式化,创建和设置holder让人累觉不爱。
- View.getTag()得到的对象需要强转为正确的holder类型,坑(查不到kludgy的翻译,只能这样了,坑)。
- 因为adapter/holder需要知道代表列表各项的view的内部结构,有违封装性。
无需ViewHolder的写法
出于复用布局的目的,原文作者定义了两个布局文件和使用merge标签来描述item的view,不过我觉得这不是这个写法的重点,所以改了一下,只是简单地定义了一个布局文件来描述item view。
先看看Demo截图
完整代码猛戳 这里
1. 定义一个Item
类来定义列表数据。
123456
public class Item {private int imgId;private String title;private String content;...getter...setter...}
2. 定义item view的布局(见item_view.xml
)。
3. 自定义ItemView
类,继承步骤2
中定义的布局的根布局(这里是RelativeLayout
),实现参数为(Context context, AttributeSet attrs)
或(Context context, AttributeSet attrs, int defStyle)
的构造方法,并添加用于获取子View对象引用、获取ItemView对象和填充数据的方法,具体代码如下:
12345678910111213141516171819202122232425262728293031
public class ItemView extends RelativeLayout {private ImageView ivImage;private TextView tvTitle;private TextView tvContent;public ItemView(Context context, AttributeSet attrs) {super(context, attrs);}// 获取ItemViewpublic static ItemView newInstance(ViewGroup parent) {ItemView view = (ItemView) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_view,parent,false);view.setupChildren();return view;}// 获取子View对象的引用private void setupChildren() {ivImage = (ImageView) findViewById(R.id.iv_image);tvTitle = (TextView) findViewById(R.id.tv_title);tvContent = (TextView) findViewById(R.id.tv_content);}// 填充数据public void populateData(Item item) {ivImage.setImageResource(item.getImgId());tvTitle.setText(item.getTitle());tvContent.setText(item.getContent());}}
4. 创建ListView用的adapter类(ItemAdapter
)。
123456789101112131415
public class ItemAdapter extends ArrayAdapter<Item> {public ItemAdapter(Context context, List<Item> objects) {super(context, 0, objects);}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ItemView view = (ItemView) convertView;if (view == null) {view = ItemView.newInstance(parent);}view.populateData(getItem(position));return view;}}
5. (很重要,我经常会忘了这步
)把item view中布局(item_view.xml)的根标签
,改为ItemView
。
123456789101112131415161718
<?xml version="1.0" encoding="utf-8"?><com.licheetec.noholderlistviewdemo.ItemView xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="64dp"android:padding="8dp"><ImageViewandroid:id="@+id/iv_image".../><TextViewandroid:id="@+id/tv_title".../><TextViewandroid:id="@+id/tv_content".../></com.licheetec.noholderlistviewdemo.ItemView>
6. 剩下的就是在activity获取和设置ListView了。
总结这种写法的优势
- Adapter的代码会变得极其简洁
- 很容易通过代码和xml文件来创建ItemView
- 以后有需要更改,只需要对布局文件和ItemView进行动刀即可
- 整个过程无需创建额外的holder类和对象
好了,基本就这样,转述可能跟原文有些出入,有能力的话可以看原文怎么说明的。
- 摆脱ViewHolder,一种无需ViewHolder的高效ListView写法
- 摆脱ViewHolder,一种无需ViewHolder的高效ListView写法
- 无需设置viewholder的Listview写法
- ListView中ViewHolder的更简单的一种写法
- ViewHolder 的一种更简洁写法
- ViewHolder的 简洁写法
- ViewHolder的简洁写法
- ViewHolder的另一种写法
- 通用ViewHolder的写法
- ViewHolder 的另类写法
- ViewHolder的简洁写法
- ViewHolder的简洁写法
- ViewHolder的简洁写法
- ViewHolder的简便写法
- ViewHolder的简洁写法
- ViewHolder的另一种写法
- ViewHolder的简便写法
- ViewHolder的另一种写法
- Axis2: services.xml的MEP(信息交换模式)配置
- 线程间操作无效: 从不是创建控件“progressBar1”的线程访问它
- LeetCode(190) Reverse Bits
- Swing多线程
- EXT2 file system inode.c with my comments
- 摆脱ViewHolder,一种无需ViewHolder的高效ListView写法
- Android简单音乐播放器
- grunt任务配置
- 构建qt4.8.6嵌入式qt环境
- jQuery和CSS3商品图片预览轮播图插件
- P51 第4题 编写一个程序,判断用户输入的字符是否是数字,若是数字,则输出“a numerical character”,否则输出“other character”.
- CentOS 6.6下安装SQLite
- sea.js+grunt学习笔记
- Josephus问题