Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >优化使用BaseAdapter

优化使用BaseAdapter

作者头像
Fisherman渔夫
发布于 2020-02-17 15:42:45
发布于 2020-02-17 15:42:45
59000
代码可运行
举报
文章被收录于专栏:渔夫渔夫
运行总次数:0
代码可运行

个人的上一篇博客,在本文中略有涉及。

本节引言:

上一节中我们学习了如何来使用一个ListView以及自定义一个简单的BaseAdapter,我们从代码中可以看出比较重要的两个方法:getCount()和getView(),界面上有多少列就会调用多少次getView, 这个时候可能看出一些端倪,每次都是新inflate一个View,都要进行这个XML的解析,这样会 很浪费资源,当然,几十列或者几百列的列表并不能体现什么问题,但假如更多或者布局更加复杂? 所以学习ListView的优化很重要,而本节针对的是BaseAdapter的优化,优化的两点有,复用convertView 以及使用ViewHolder重用组件,不用每次都findViewById,我们具体通过代码来体会吧!


1.复用ConvertView:

上面也说了,界面上有多少个Item,那么getView方法就会被调用多少次! 我们来看看上一节我们写的getView()部分的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//下面这个赋值语句和行数线性相关,资源太浪费了!
    convertView = LayoutInflater.from(mContext).inflate(R.layout.item_list_animal,parent,false);
    ImageView img_icon = (ImageView) convertView.findViewById(R.id.img_icon);
    TextView txt_aName = (TextView) convertView.findViewById(R.id.txt_aName);
    TextView txt_aSpeak = (TextView) convertView.findViewById(R.id.txt_aSpeak);

    img_icon.setBackgroundResource(mData.get(position).getaIcon());
    txt_aName.setText(mData.get(position).getaName());
    txt_aSpeak.setText(mData.get(position).getaSpeak());
    return convertView;
}

是吧,inflate()每次都要加载一次xml,其实这个convertView是系统提供给我们的可供服用的View 的缓存对象,那就坐下判断咯,修改下,优化后的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
public View getView(int position, View convertView, ViewGroup parent) {

    if(convertView == null){
        convertView = LayoutInflater.from(mContext).inflate(R.layout.item_list_animal,parent,false);
    }

    ImageView img_icon = (ImageView) convertView.findViewById(R.id.img_icon);
    TextView txt_aName = (TextView) convertView.findViewById(R.id.txt_aName);
    TextView txt_aSpeak = (TextView) convertView.findViewById(R.id.txt_aSpeak);

    img_icon.setBackgroundResource(mData.get(position).getaIcon());
    txt_aName.setText(mData.get(position).getaName());
    txt_aSpeak.setText(mData.get(position).getaSpeak());
    return convertView;
}

 convertView能够被复用的的最根本原因是:ListView的每一行的View对象结构都是类似的,就拿我的前一篇关于ListView的文章为例,每一行布局的结构都是如下图所示:

每一次调用如果都通过:

convertView = LayoutInflater.from(mContext).inflate(R.layout.item_list_animal,parent,false);

 新建一个结构完全相同的控件,这是浪费的,所以在第一行布局完成后,我们还是可以利用这个布局对象,只是需要对其重新赋值,比如说改为图片2;改为str_a1改为str_a2;str_b1改为str_b2,如下图所示:

2.ViewHolder重用组件

嘿嘿,getView()会被调用多次,那么findViewById不一样得调用多次,而我们的ListView的Item 一般都是一样的布局,我们可以对这里在优化下,我们可以自己定义一个ViewHolder类来对这一部分进行性能优化!

这里还是这样的原因,以下三个语句对象的构造还是和1.中有相同的原理,随着行数的增多线性增多调用的次数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ImageView img_icon = convertView.findViewById(R.id.img_icon);

TextView text_aName = convertView.findViewById(R.id.txt_aName);

TextView text_aSpeak = convertView.findViewById(R.id.txt_aSpeak);

 所以我们需要通过类似的判断,如果img_icon为空,那么调用findViewById()方法返回此对象引用,否则跳过此步骤,直接调用相关set方法进行资源的覆盖赋值即可。那么对于text_name以及text_aSpeak对象也是同理,但是这么多的判断语句写在一起实在不方便,过多的判断语句效率也不见得高,所以就将这些判断使用一个ViewHolder对象集成起来。只要判断ViewHolder对象是否为空即可。

修改后的代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder = null;
    if(convertView == null){
        convertView = LayoutInflater.from(mContext).inflate(R.layout.item_list_animal,parent,false);
        holder = new ViewHolder();
        holder.img_icon = (ImageView) convertView.findViewById(R.id.img_icon);
        holder.txt_aName = (TextView) convertView.findViewById(R.id.txt_aName);
        holder.txt_aSpeak = (TextView) convertView.findViewById(R.id.txt_aSpeak);
        convertView.setTag(holder);   //将Holder存储到convertView中
    }else{
        holder = (ViewHolder) convertView.getTag();
    }
    holder.img_icon.setBackgroundResource(mData.get(position).getaIcon());
    holder.txt_aName.setText(mData.get(position).getaName());
    holder.txt_aSpeak.setText(mData.get(position).getaSpeak());
    return convertView;
}

static class ViewHolder{
    ImageView img_icon;
    TextView txt_aName;
    TextView txt_aSpeak;
}

 实际没有 ViewHolder 对象,更没有判断ViewHolder是否为空的语句,因为从执行顺序上来说,只要有一行初始化过了 convertView 对象,那么一定就会有初始化img_icon 、txt_aName 、txt_aSpeak 这三个对象,所以我们只需要判断 convertView 对象是否为空即可。而为何将ViewHolder设置为静态类的原因可以用如下B神的话来描述:

没错就是这么简单,你以后BaseAdapter照着这个模板写就对了,哈哈,另外这个修饰ViewHolder的 static,关于是否定义成静态,跟里面的对象数目是没有关系的,加静态是为了在多个地方使用这个 Holder的时候,类只需加载一次,如果只是使用了一次,加不加也没所谓!——Berial(B神)原话~


本节小结:

好的,关于BaseAdapter的优化大概就上述的两种,非常简单,复用ConvertView以及自定义ViewHolder 减少findViewById()的调用如果你有其他关于BaseAdapter优化的建议欢迎提出,谢谢

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Andorid-ListView简单使用以及BaseAdapter入门
一个很简单的ListView,自己写下Item,然后加载点数据这样~ 下面贴下关键代码:
Fisherman渔夫
2020/02/19
1.5K0
每点击一次按钮就添加一条数据
需求 每点击一次按钮就添加一条数据(图片+文字) 项目目录 .java .domain Data package top.gaojc.calculator.domain; public class Data { private int imgId; private String content; public Data() {} public Data(int imgId, String content) { this.imgId = img
是阿超
2021/10/15
9600
ListView使用技巧-更新中
虽然在Android5.X中,RecyclerView在很多地方组件取代了ListView,但是ListView的使用依然是分广泛。
小小工匠
2021/08/16
1.1K0
笔记42 | Android加载器Adapter的深入学习篇(一)
地址 CSDN:http://blog.csdn.net/xiangyong_1521/article/details/78653538简书:http://www.jianshu.com/p/7bfd1eeea5cb ---- 目录 以ListView为例的工作原理 ViewHolder的作用 getItemViewType和getViewTypeCount 实现 实现步骤 ---- 1.ListView针对List中每个item, adapter都会调用一个getView的方法获得布局视图 2.我们一般
项勇
2018/06/19
6260
Android:适配器(Adapter)的使用
如果在xml中将信息写死,那显然是不合适的,无法做到上拉刷新的效果。 这个时候,就需要用到适配器。
zstar
2022/06/14
1.1K0
Android:适配器(Adapter)的使用
ListView优化和列表首尾使用
前面连续几期都在学习ListView的各种使用方法,如果细心的同学可能会发现其运行效率是有待提高的,那么本期就来一起学习有哪些方法技巧来优化ListView的效率。 一、使用convertView 前面讲的自定义ArrayAdapter和自定义BaseAdapter,都会重写getView()方法,虽然可以正常使用,但其实效率非常低。当列表项很多时,用户每次滚动屏幕,都会创建一批新的View对象,以填充新出现的列表项,这样势必会影响用户体验。 我们可以看到getView()方法中传入
分享达人秀
2018/02/02
1.6K0
ListView优化和列表首尾使用
Kotlin入门(22)适配器的简单优化
为实现各种排列组合类的视图(包括但不限于Spinner、ListView、GridView等等),Android提供了五花八门的适配器用于组装某个规格的数据,常见的适配器有:数组适配器ArrayAdapter、简单适配器SimpleAdapter、基本适配器BaseAdapter、翻页适配器PagerAdapter。适配器的种类虽多,却个个都不好用,以数组适配器为例,它与Spinner配合实现下拉框效果,其实现代码纷复繁杂,一直为人所诟病。故而在下拉框一小节之中,干脆把ArrayAdapter连同Spinner一股脑都摒弃了,取而代之的是Kotlin扩展函数selector。 到了列表视图ListView这里,与之搭档的一般是基本适配器BaseAdapter,这个BaseAdapter更不简单,基于它的列表适配器得重写好几个方法,还有那个想让初学者撞墙的ViewHolder。总之,每当要实现类似新闻列表、商品列表之类的页面,一想到这个难缠的BaseAdapter,心里便发怵。譬如下图所示的六大行星的说明列表,左侧是图标,右边为文字说明,很普通的一个页面。
aqi00
2019/01/18
1.4K0
关于ListView中包含EditText数据复用引起异常的解决方案
概述 前几天测试提了一个bug,在ListView中添加留言信息,导致错乱的问题。实际上就是ListView需要添加一个EditText,复用导致错乱的问题,这个问题以前也遇到过。诸如,ListVie
xiangzhihong
2018/02/05
1.7K0
关于ListView中包含EditText数据复用引起异常的解决方案
Android开发-Listview中显示不同的视图布局
在重写ListView的BaseAdapter时,我们常常在getView()方法中复用convertView,以提高性能。convertView在Item为单一的同种类型布局时,能够回收并重用,但是多个Item布局类型不同时,convertView的回收和重用会出现问题。比如有些行为纯文本,有些行则是图文混排,这里纯文本行为一类布局,图文混排的行为第二类布局。单一类型的ListView很简单,下面着重介绍一下ListView包含多种类型视图布局的情形。
他叫自己MR.张
2019/07/01
2.6K0
【Android】Android对于Activity的运用以及ViewGroup和 用户界面组件在项目中的运用
确保无论系统从哪个任务启动活动,都只会创建一个活动实例并将其添加到新任务堆栈的顶部,也就是说,该实例启动的其他活动将自动在另一个任务中运行。再次启动此活动的实例时,将重用现有任务和实例。将调用此实例的onNewIntent()方法,将Intent实例传递给此实例。与singleTask一样,系统中同时只有一个这样的活动实例。
上进小菜猪
2022/12/27
7560
【Android】Android对于Activity的运用以及ViewGroup和 用户界面组件在项目中的运用
Android ListView适配器应该这样写
ViewHolder缓存View的思路我们还是要继续沿用,但是我们希望ViewHolderHelper能够适用所有Adapter,而且我们希望它能有更强大功能,例如能够设置显示的文本,能够设置点击事件等。
三好码农
2018/09/11
5690
Andriod基础——Adapter类
Android是完全遵循MVC模式设计的框架,Activity是Controller,layout是View,因为layout五花八门,很多数据都不能直接绑定上去,所以Android引入了Adapte
mukekeheart
2018/02/27
1.7K0
Andriod基础——Adapter类
android 在 ListView 的 item 中插入 GridView 仿微信朋友圈图片显示。
根据文章内容,该文介绍了如何通过代码实现一个炫酷的微信小程序,包括自定义组件、动态设置样式、动画、异步加载和封装自定义组件等。同时,作者还提供了示例代码和详细的注释,方便读者理解和学习。
林冠宏-指尖下的幽灵
2018/01/03
2.5K0
android 在 ListView 的 item 中插入 GridView 仿微信朋友圈图片显示。
Carson带你学Android:全面解析列表ListView与AdapterView
2. 在MainActivity上定义一个链表,将所要展示的数据以存放在里面 3. 构造ArrayAdapter对象,设置适配器 4. 将LsitView绑定到ArrayAdapter上 如下图:
Carson.Ho
2022/03/24
1.2K0
Carson带你学Android:全面解析列表ListView与AdapterView
Android开发:ListView、AdapterView、RecyclerView全面解析
AdapterView本身是一个抽象类,AdapterView及其子类的继承关系如下图:
Carson.Ho
2019/02/22
3.6K0
Android ListView 删除 item
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/160603.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/13
7840
Android ListView 删除 item
listview加载性能优化之view的复用
在android开发中Listview是一个很重要的组件,它以列表的形式根据数据的长自适应展示具体内容,用户可以自由的定义listview每一列的布局,但当listview有大量的数据需要加载的时候,会占据大量内存,影响性能,这时候就需要按需填充并重新使用view来减少对象的创建。
再见孙悟空_
2023/02/10
3880
ListView数据动态更新
经过前面几期的学习,关于ListView的一些基本用法大概学的差不多了,但是你可能发现了,所有ListView里面要填充的数据都是静态的,但在实际开发中,这些数据往往都是动态变化的,比如数据内容发生改变、增加几行、或者删除几行,这就涉及到ListView数据的更新问题。 接下来通过一个简单的示例程序来学习ListView的数据更新。 继续使用WidgetSample工程,在app/main/res/layout/目录下创建updatedata_layout.xml文件,在其中填充如下
分享达人秀
2018/02/02
2.3K0
ListView数据动态更新
android入门 — ListView的优化
  ListView的运行效率是比较低的,因为在getView()中每次都会将整个布局重新加载一遍,当ListView快速滚动的时候就会成为性能瓶颈。   调用View中的findViewById()方法获取一次控件的实例,这也是一个很耗时的操作,可以进行优化。 方法一:convertView参数 这个参数用于将之前加载好的布局进行缓存,以便之后进行重用。 @Override public View getView(int position, View convertView, View
Mister24
2018/05/14
9452
相关推荐
Andorid-ListView简单使用以及BaseAdapter入门
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验