ListView这么优化

Android ListView高效实现与优化教程 本文还有配套的精品资源,点击获取 简介:ListView是Android中用于展示列表数据的关键组件, MyListView 项目提供了实际的代码示例,帮助开发者掌握如何高效使用ListView。课程内容涵盖了ListView的基础结构、Adapter模式、ViewHolder优化、监听器设置、性能优化、下拉刷新与上拉加载、自定义ListView、动画效果、数... 阅读详情

提升Android ListView性能的几个技巧

ListView如何运作的?

ListView是设计应用于对可扩展性和高性能要求的地方。实际上,这就意味着ListView有以下2个要求:

  1. 尽可能少的创建View;
  2. 只是绘制和布局在屏幕上可见的子View。

理解第一点很简单:通过布局xml文件在创建View并显示是很昂贵耗时耗资源的操作。尽管布局文件已经编译打包成了二进制形式以便于更高效的语法解析,但是创建View仍然需要通过一个特殊的XML树,并实例化所有需要响应的View。

ListView通过回收一些不可见的Views,通常在Android源码中称为“ScrapView(废弃的View)”来解决这个问题。这及意味着开发者只需要简单的更新每行的内容而不需要针对每个单独的行的布局来创建View。

为了实现第二点,在我们滑动屏幕时,ListView通过使用View回收器来增加低于或者高于当当前窗口的Views,并当前活动的Views移动到一个可回收池中。这样的话,ListView只需要在内存中保持足够多的Views去填充分配空间中的布局和一些额外的可回收Views,即使当你的Adapter有上百个items的适合。它会使用不同的方法去填充行之间的空间,从顶部或者底部等等,具体取决于窗口是如何变化的。

下面这个图很直观的展示了当你按下ListView的时候发生了什么:

通过上述介绍,相比我们已经熟悉了ListView的这种机制,让我们继续前往技巧部分。正如上述介绍的,在滑动时,ListView通过动态的创建和回收很多View,实现了尽可能地让Adapter的getView()轻量。所有的技巧都是通过多种方法让getView()更快。

View的回收

当ListView每次需要在屏幕上显示新的一行的时候,会从其Adapter中调用getView()的方法。众所周知,getView()方法有3个参数:行的位置, convertView以及父ViewGroup。

参数convertView说穿来就是之前讲述的ScrapView。当ListView要求更新一行的布局时,convertView是一个非空值。因此,当convertView值非空时,你仅仅需要更新内容即可,而不需要重新一个新行的布局。getView()在Adapter中一般是如下的形式:

public View getView(int position, View convertView, ViewGroup parent) {     if (convertView == null) {         convertView = mInflater.inflate(R.layout.your\_layout, null);     }      TextView text = (TextView) convertView.findViewById(R.id.text);     text.setText("Position " + position);      return convertView; }

View Holder如何写的模板

Android很常见的一个操作就是在布局文件中找到一个内部的View。通常是使用一个findViewById()的View方法来实现的。这个findViewById()方法在View树中,根据一个View ID,会递归的被调用来找到其子树。虽然在静态UI布局中使用findViewById()是完全正常的。但是,在滑动时,ListView调用其Adapter中的getView()是非常频繁的。findViewById()可能会影响ListView滑动时的性能,尤其是你的行布局是很复杂的时候。

寻找一个充气布局内的内部观点是在Android上最常用的操作之一。这通常是通过一个名为findViewById(查看方法完成)。此方法将递 归经过视图树寻找一个孩子用给定的ID码。静态的UI布局使用findViewById()是完全正常,但正如你所看到的,ListView中滚动时调用 适配器的getView()非常频繁。 findViewById()可能perceivably击中ListViews,尤其是滚动的性能,如果你行的布局是不平凡的。

View Holder的模式就是减少在Adapter中getView()方法中调用findViewById()次数。实际上,View Holder是一个轻量级的内部类,用于直接引用到所有内部views。在创建View之后,你可以在每行的View存储为一个标签。通过这种方法,只需要在初次创建布局的时候调用findViewById()。下面是一个使用上述方法的View Holder模板的代码示例:

 public View getView(int position, View convertView, ViewGroup parent) {     ViewHolder holder;      if (convertView == null) {         convertView = mInflater.inflate(R.layout.your\_layout, null);          holder = new ViewHolder();         holder.text = (TextView) convertView.findViewById(R.id.text);          convertView.setTag(holder);     } else {         holder = convertView.getTag();     }      holder.text.setText("Position " + position);      return convertView; }  private static class ViewHolder {     public TextView text; } 

异步加载

很多时候,Android应用在ListView每行中显示一些多媒体内容,比如图片等。在Adapter中的getView()使用应用内置的图片资源还是不会出什么问题的,因为可以存储在Android的高速缓存中。但当你想多态的显示来自本地磁盘或网络的内容时,例如缩略图,简历图片等。在这种情况下,你可能不希望直接在Adapter中的getView()加载它们,因为IO进程会阻塞UI线程。如果这样做的话,ListView就看起来非常卡顿。

在一个单独的线程,如果想要运行的所有行的IO操作或任何高负载CPU限制的异步操作。其中的技巧就是要做到符合ListView的回收行为。例如,如果在Adapter中的getView()中,使用AsyncTask的加载去加载资料图片,在AsyncTask完成之前,你正在加载的图片View就有可能被回收用于其他地方。所以,一旦异步操作完成的同时,需要一种机制来知道如果相应的View有没有被回收。

一个简单的方法来实现这一目标是通过附加一些标识该行与它相关的View的信息。然后,当异步操作完成的适合,检查目标行的View和标识的View是否一致。实现这一目标的方法很多。下面是实现这种方法的一个很简单的示例:

 public View getView(int position, View convertView,         ViewGroup parent) {     ViewHolder holder;      ...      holder.position = position;      new ThumbnailTask(position, holder)             .executeOnExecutor(AsyncTask.THREAD\_POOL\_EXECUTOR, null);      return convertView; }  private static class ThumbnailTask extends AsyncTask {     private int mPosition;     private ViewHolder mHolder;      public ThumbnailTask(int position, ViewHolder holder) {         mPosition = position;         mHolder = holder;     }      @Override     protected Cursor doInBackground(Void... arg0) {         // Download bitmap here     }      @Override     protected void onPostExecute(Bitmap bitmap) {         if (mHolder.position == mPosition) {             mHolder.thumbnail.setImageBitmap(bitmap);         }     } }  private static class ViewHolder {     public ImageView thumbnail;     public int position; } 

人机交互知识

做到在每一行异步加载很多资源,是一个高性能的ListView的必经之路。但是,在滑动屏幕时,如果你一味的在每一个getView()调用里面都去启动一个异步的操作,造成的结果就是你会浪费大量资源。因为行被频繁回收,造成大部分返回的结果会被丢弃。

考虑到实际的人机交互情况,在ListView适配器中,在每一行中都不应该去触发任何异步操作。也就是说,在ListView中有fling(快速滑动)操作时,启动任何异步操作都没有任何意义。一旦滚动停止或即将停止,才是开始真正显示每行的内容的时候。

我不会发布一个代码示例贴在这里,因为其中涉及到的代码太多。Romain Guy写了一个很经典的应用:Shelves app,其中有一个很好的的示例。当GridView停止滑动时不做其他事情时,它就开始触发从而去异步加载书的封面资源。即使在滑动时,你也可以展示缓存中的内容,通过使用memory cache来平衡交互。这真是个好主意!

以上

我强烈推荐你看下Romain Guy和Adam Powell的关于ListView的讨论,里面涵盖了很多这篇文章的东西。你可以看看Pattrn,可以看到这里面的几个技巧是如何在应用中运用的。

更多的完整优化经验以及学习资料可以扫码免费领取!

《Android 性能优化实战篇》

目录

imgimg

img

rv1126平台spi屏调试 st7789v2 i2c调试 阅读详情

相关推荐

新手必看!Unity中Tag和Layer的7个实际应用场景(含MOBA案例)

本文深入探讨Unity中Tag和Layer的7个实际应用场景,特别以MOBA游戏开发为例,详细解析如何利用LayerMask进行高效场景管理和碰撞检测优化。从双相机方案到射线检测的精准控制,帮助开发者掌握这些基础功能的进阶用法,提升游戏性能和开发效率。

weixin_28723171的博客 313

ListView的一些优化

介绍listview的一些优化以及从服务器加载图片时出现的错乱问题。

小胜御风的博客 363

STM32-DAC定时器触发三角波生成【频率与幅度精准控制】

本文详细介绍了STM32 DAC定时器触发三角波生成的原理与实现方法,涵盖硬件配置、频率与幅度精准控制技巧及代码实现。通过定时器触发DAC模块,可灵活调节三角波的频率和幅度,适用于信号发生器等高精度应用场景。

weixin_29161785的博客 454

优化ImageView,在使用ListView或GridView的时候,每次更新图片的时候,在显示新的图片和旧的图片一样大小的时候,不需要去重新计算大小

OptimisedImageView.java外部引用原始文档 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

宝爷的专栏 1101

合成孔径雷达(SAR)的常见工作模式

随着星载SAR技术研究的深入发展,单一的条带模式已经无法满足当今时代的需求,因此许多新的工作模式相继被提出。这些新模式在分辨率和测绘宽度等方面都有所提高,接下来将简要介绍几种常用的工作模式。

m0_51390495的博客 2317

浊音/清音/爆破音的时域及频域特性

第一周作业 浊音/清音/爆破音的时域及频域特性 思路:使用Audacity进行录制,时域部分将音频放大观察波形规律,频域部分生成并进行频谱分析。 (1)浊音U 时域分析: 时域表现为短周期性,波形比较规律。 频域分析: 频域上表现为频率集中在低频区域,共振峰较为明显,短时能量较高。 (2)清音S 时域分析: 时域波形没有周期性,整体振幅小于浊音。 频域分析: 频域波形平缓,无共振峰,能量比较集中。 (3)爆破音t 时域分析: 脉冲波,更为尖锐,整体上振幅降低。 频域分析: 没有像浊音一样的共振

Leylaaaa的博客 1228

ListView各种优化方法

一.ListView如何提高效率 当convertView为空时,用setTag()方法绑定一个存放控件的ViewHolder对象。当convertView不为空,重复利用 已经创建的view的时候,使用getTag()方法获取绑定的ViewHolder对象,这样就避免了findViewById对控件的层 层查询。 (1)复用ConvertView,使用历史的view (2)自定义静态类

liuke 1458

MPU6050模块DIY翻车实录:ID能读但数据全为零?原来是这个10uF电容惹的祸

本文详细记录了MPU6050模块调试过程中遇到的ID能读但数据全为零的问题排查过程。通过对比不同参考设计,发现CPOUT引脚10uF电容选择不当是导致数据异常的根源,更换为官方推荐的2.2nF电容后问题解决。文章为硬件开发者提供了宝贵的电路设计经验。

weixin_29158047的博客 319

ListView优化方案和原理,你都知道了嘛?

1.重用ConvertView ListView的View回收机制:在可视范围上面或者下面的View加入到回收池中。当在可视范围内的View被移出可视范围内时,其也会被添加到回收池中。以这种方式ListView只需占用非常少的内存几可以存储可视范围内的View和回收池中的View。 参数convertView实际上就是一个可回收的View。当ListView要回收这个View的时候,它的数据就会被...

twistfatey的博客 474

强化学习——day16 动态规划算法

动态规划(dynamic programming)是程序设计算法中非常重要的内容,能够高效解决一些经典问题,例如背包问题和最短路径规划。动态规划的基本思想是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到目标问题的解。动态规划会保存已解决的子问题的答案,在求解目标问题的过程中,需要这些子问题答案时就可以直接利用,避免重复计算。本章介绍如何用动态规划的思想来求解在马尔可夫决策过程中的最优策略

想太多的学习日志 1551

[Linux]双网卡 CentOS 系统中指定网络请求走特定网卡的配置方法

本文详细介绍了在双网卡CentOS系统中指定特定域名/IP通过指定网卡传输流量的方法。核心步骤包括:1)确认网卡信息(ip addr)和域名IP解析(nslookup);2)添加临时路由(ip route add);3)持久化配置(创建route-eth1文件);4)验证配置(ip route show和curl测试)。文章还提供了网关查询、路由删除等常见问题的解决方法,并区分了不同CentOS版本重启网络服务的命令差异。通过合理配置路由规则,可实现流量的定向传输需求。

wingaso的博客 1573

【提升栈】ListView优化

ListView优化

Android23333的博客 717

使用DrissionPage实现携程酒店信息智能爬取

本文介绍了一个基于DrissionPage技术的携程酒店信息爬虫系统,通过监听API数据包实现高效采集。系统可自动获取酒店名称、价格、评分、位置等15个维度的数据,支持多页滚动加载和智能去重。相比传统爬虫,该方法直接解析API返回的JSON数据,避免了复杂的HTML解析和加密参数分析,提高了开发效率和稳定性。文章详细阐述了13个关键实现步骤,并强调数据采集应严格遵守法律法规,仅用于技术学习和市场研究。该系统可为旅游决策、价格监测等提供数据支持,但需注意合理使用频率和隐私保护。

那些看似不起波澜的日复一日,会在某天让你看到坚持的意义 392

listview优化方案

优化方向: 1、 利用convertView缓存的布局减少创建listview item的数量,尽可能复用以前创建的 2、利用viewholder机制,尽可能的减少 findviewbyid这一类的查找控件的操作。如果要复用布局,则同时将查找到的控件存储起来(setFlag),下次使用的时候可以直接用(getFlag)。 示例代码 示例代码解析: 见一个viewholder的类,把所有用到的控...

ITzhongzi的博客 430

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

ListView的简单优化

原理:创建一个容器装要复用的View,设置判断,达到减少findViewById的次数的效果 MainActivity如下,这个比较简单就不解释了 主要讲下适配器: 继承BaseAdapter后实现四个方法 具体解释如下图(两图是一起的,最后会放源码) 上图所示:在getview方法中有三个参数,起到优化的部分为ViewHolder的使用,主要方法setTag(),getTag()。 适配器代...

计蒙不吃鱼的博客 8509

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

ListView的优化

【代码】ListView的优化。

weixin_43956070的博客 522

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

ListView优化

Android性能优化-ListView ListView的优化主要分为以下几点 1 convertView的复用 ListView每次滚动都会调用getView方法,所以优化getVieiw是重中之重 convertView介绍 convertView是刚刚滚动出可见区域的View的引用,此时它已经不可见,所以应该被复用以减少View的创建 优化代码 View view = null;//getView方法要返回的View if(convertView == null){//如果当前没有可以复用的View

small_bat的博客 574

android ListView优化

作为一个android开发不知道多少年的开发者来说,除了四大组件之外,我觉得开发过程中最需要注意的就是在使用listview的优化。关于listview的优化我有几个心得:未优化的代码:public View getView(int position, View convertView, ViewGroup parent) { final yuangongBean.DataBean pro...

丁辉祥的博客 2492

Android之ListView原理学习与优化总结

2.3:在ListView中取图片时也不要直接拿个路径去取图片,而是以WeakReference(使用WeakReference代替强引用。比如可以使 用WeakReference mContextRef)、SoftReference、WeakHashMap等的来存储图片信息,是图片信息不是图片哦!2.4:在getView中做图片转换时,产生的中间变量一定及时释放,用以下形式:**bmp.recycle() //回收图片所占的内存。6.1:将线程的内部类,改为静态内部类。

2401_89690178的博客 1061

Listview优化总结

Listview是andorid中最常用的控件之一,但要用好这个控件并不是那么容易。不注意优化的使用经常出现页面卡顿,OOM等问题的出现。在此本人将自己的拙见整理汇总,归纳listview的优化措施。 1.复用convertView 2.viewHolder保存控件 3.分页加载 4.UI卡顿优化 5.OOM

Hubert的博客 863

ListView优化功能

//初始化组件 listView = (ListView) findViewById(R.id.ListView); text_title = (TextView) findViewById(R.id.text_title); //设置标题 text_title.setText("数据展示"); list = new ArrayList<Bea...

qq_44574528的博客 289

listview 优化

XML: &lt;ListView android:id="@+id/list_view" android:layout_width="match_parent" android:layout_height="match_parent" /&gt; 主页: public class MainActivity extends...

NIJIADALINGE的博客 184

性能优化之ListView优化

等等呢个 转载于:https://my.oschina.net/u/3491256/blog/906357

chuanwang3181的博客 88
上一篇: 【震大惊】Java程序员学习Kotlin
下一篇: 这样的面试你还去吗
不秃头de程序猿
博客等级 码龄5年 4089粉丝 1478原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值