Android进阶笔记12:ListView篇之图片优化
1、图片异步加载:
(1)处理图片的方式:
如果ListView中自定义的Item中有涉及到大量图片的,一定要对图片进行细心的处理,因为图片占的内存是 ListView 项中最头疼的,处理图片的方法大致有以下几种:
①、不要直接拿路径就去循环 BitmapFactory.decodeFile;使用 Options 保存图片大小、不要加载图片到内存去。
②、对图片一定要经过边界压缩尤其是比较大的图片,如果你的图片是后台服务器处理好的那就不需要了。
③、在 ListView 中取图片时也不要直接拿个路径去取图片,而是以 WeakReference(使用 WeakReference 代替强引用。比如可以使用 WeakReference mContextRef)、SoftReference、 WeakHashMap 等的来存储图片信息。
④、在 getView 中做图片转换时,产生的中间变量一定及时释放。
(2)异步加载图片基本思想:
1)、 先从内存缓存中获取图片显示(内存缓冲)
2)、获取不到的话从 SD 卡里获取(SD 卡缓冲)
3)、都获取不到的话从网络下载图片并保存到SD卡同时加入内存并显示(视情况看是否要显示)
原理:
优化一:先从内存中加载,没有则开启线程从 SD 卡或网络中获取,这里注意从 SD 卡获取图片 是放在子线程里执行的,否则快速滑屏的话会不够流畅。
优化二:于此同时,在 adapter 里有个 busy 变量,表示 listview 是否处于滑动状态,如果是滑动状态则仅从内存中获取图片,没有的话无需再开启线程去外存或网络获取图片。
优化三:ImageLoader 里的线程使用了线程池,从而避免了过多线程频繁创建和销毁,如果每次总是 new 一个线程去执行这是非常不可取的,好一点的用的 AsyncTask 类,其实内部也是用到了线程池。在从网络获取图片时,先是将其保存到 sd 卡,然后再加载到内存,这么做的好处是在加载到内存时可以做个压缩处理,以减少图片所占内存。
2. ListView图片错位的原因 和 图片错位的解决方法:
(1)ListView图片错位的原因:

Listview 异步加载图片之所以错位的根本原因是重用了 convertView 且有异步操作。如果不重用 convertView 不会出现错位现象,重用 convertView 但没有异步操作也不会有问题。
我简单分析一下:
当重用 convertView 时,最初一屏显示 7 条记录, getView 被调用 7 次,创建了 7 个 convertView。当 Item1 划出屏幕, Item8 进入屏幕时,这时没有为 Item8 创建新的 view 实例, Item8 复用的是Item1 的 view 如果没有异步不会有任何问题,虽然 Item8 和 Item1 指向的是同一个 view,但滑到Item8 时刷上了 Item8 的数据,这时 Item1 的数据和 Item8 是一样的,因为它们指向的是同一块内存,但 Item1 已滚出了屏幕你看不见。当 Item1 再次可见时这块 view 又涮上了 Item1 的数据。
但当有异步下载时就有问题了,假设 Item1 的图片下载的比较慢,Item8 的图片下载的比较快,你滚上去使 Item8 可见,这时 Item8 先显示它自己下载的图片没错,但等到 Item1 的图片也下载完时你发现Item8 的图片也变成了 Item1 的图片,因为它们复用的是同一个 view。 假设 Item1 的图片下载的比Item8 的图片快,Item1 先刷上自己下载的图片,这时你滑下去,Item8 的图片还没下载完, Item8会先显示 Item1 的图片,因为它们是同一块内存,当 Item8 自己的图片下载完后 Item8 的图片又刷成了自己的,你再滑上去使 Item1 可见, Item1 的图片也会和 Item8 的图片是一样的,因为它们指向的是同一块内存。
(2)图片错位的解决方法:
// 给 ImageView 设置一个 tag
holder.img.setTag(imgUrl);
// 预设一个图片
holder.img.setImageResource(R.drawable.ic_launcher); // 通过 tag 来防止图片错位
if (imageView.getTag() != null && imageView.getTag().equals(imageUrl)) {
imageView.setImageBitmap(result);
}
Android进阶笔记12:ListView篇之图片优化的更多相关文章
- android学习笔记12——ListView、ListActivity
ListView.ListActivity ==> ListView以垂直列表的形式显示所有列表项. 创建ListView的方式: 1.直接使用ListView创建 2.Activity继承Li ...
- Android进阶笔记15:ListView篇之图片优化
1.图片异步加载: (1)处理图片的方式: 如果ListView中自定义的Item中有涉及到大量图片的,一定要对图片进行细心的处理,因为图片占的内存是 ListView 项中最头疼的,处理图片的方法大 ...
- Android进阶笔记12:Manymo(在线安卓系统模拟器工具)
Manymo: 在线安卓系统模拟器工具是一款启动速度快,且在浏览器中就能运行流畅.你可以使用它来测试你的安卓应用,他最多能支持42种屏幕尺寸和系统版本. 长久以来,Android开发者面临的困境之一就 ...
- Android进阶笔记:Messenger源码详解
Messenger可以理解为一个是用于发送消息的一个类用法也很多,这里主要分析一下再跨进程的情况下Messenger的实现流程与源码分析.相信结合前面两篇关于aidl解析文章能够更好的对aidl有一个 ...
- Android进阶笔记:AIDL内部实现详解 (二)
接着上一篇分析的aidl的流程解析.知道了aidl主要就是利用Ibinder来实现跨进程通信的.既然是通过对Binder各种方法的封装,那也可以不使用aidl自己通过Binder来实现跨进程通讯.那么 ...
- Spring源码学习笔记12——总结篇,IOC,Bean的生命周期,三大扩展点
Spring源码学习笔记12--总结篇,IOC,Bean的生命周期,三大扩展点 参考了Spring 官网文档 https://docs.spring.io/spring-framework/docs/ ...
- Android进阶笔记16:ListView篇之ListView刷新显示(全局 和 局部)
一.ListView内容变化后,动态刷新的步骤(全局刷新): (1)更新适配器Adapter数据源:(不要使用匿名内部类) (2)调用适配器Adapter的刷新方法notifyDataSetChang ...
- Android进阶笔记13:ListView篇之ListView刷新显示(全局 和 局部)
一.ListView内容变化后,动态刷新的步骤(全局刷新): (1)更新适配器Adapter数据源:(不要使用匿名内部类) (2)调用适配器Adapter的刷新方法notifyDataSetChang ...
- Android进阶笔记14:ListView篇之ListView性能优化
1. 首先思考一个问题ListView如何才能提高效率 ? 当convertView为空时候,用setTag()方法为每个View绑定一个存放控件的ViewHolder对象.当convertView不 ...
随机推荐
- java中的线程(3):线程池类 ThreadPoolExecutor「线程池的类型、参数、扩展等」
官方文档: https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html 1.简介 pu ...
- UI设计师与VI设计师的区别
企业视觉形象(CorporateVisualImage)与企业视觉形象识别(VI)并不是一个概念.前者是企业与生俱来的客观存在要素,也就是说一个企业无论是否制定了它的VI,也无论其所制定的VI是否成功 ...
- mysql 显示树结构表的节点全路径
SELECT TYPEID AS TYPEID, pTYPEID AS 父TYPEID, levels AS 父到子之间级数, concat(paths, ',', TYPEID) AS 父到子路径, ...
- Notepad++的ftp远程编辑功能
我们主要来说说NppFTP的使用方法: 1.启动notepad++后,点击插件-->NppFTP-->Show NppFTP Window,就可以显示NppFTP的管理窗口了. 2.在Np ...
- 遇见phpDesigner我笑了 PHP开发利器
phpDesigner实在太好用了 相信许多PHP同胞谈到PHP开发工具的时候,都会想到Zend Studio.Eclipse等开发工具,这些工具的确非常的强大强悍,但复杂的配置满屏幕的英文并不适合所 ...
- PHP SECURITY CALENDAR 2017 学习总结-更新中
这篇文章主要以审计代码为主来分析每道题目中所存在的漏洞点,记录一下自己的学习: 1.Day 1 - Wish List class Challenge { const UPLOAD_DIRECTORY ...
- 使用ANY、Some或All关键字
可以使用All或Any关键字修改引入子查询的比较运算符.Some是与Any等效的ISO标准,All要求Where表达式与子查询返回的每个值进行比较时都应满足比较条件,Any则要求Where表达式与子查 ...
- java常用API之字符串缓冲区
StringBuffer类: StringBuffer是个字符串的缓冲区,是可变的字符串数组,即就是它是一个容器,容器中可以装很多字符串.并且能够对其中的字符串进行各种操作 StringBuffer的 ...
- bind 事件名称 命名空间
1.通过在事件名称后面添加以点号分隔的后缀来为事件名称指派命名空间 $("#button").bind("click.editMode",function(){ ...
- cf1072D. Minimum path(BFS)
题意 题目链接 给出一个\(n \times n\)的矩阵,允许修改\(k\)次,求一条从\((1, 1)\)到\((n, n)\)的路径.要求字典序最小 Sol 很显然的一个思路是对于每个点,预处理 ...