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篇之图片优化的更多相关文章

  1. android学习笔记12——ListView、ListActivity

    ListView.ListActivity ==> ListView以垂直列表的形式显示所有列表项. 创建ListView的方式: 1.直接使用ListView创建 2.Activity继承Li ...

  2. Android进阶笔记15:ListView篇之图片优化

    1.图片异步加载: (1)处理图片的方式: 如果ListView中自定义的Item中有涉及到大量图片的,一定要对图片进行细心的处理,因为图片占的内存是 ListView 项中最头疼的,处理图片的方法大 ...

  3. Android进阶笔记12:Manymo(在线安卓系统模拟器工具)

    Manymo: 在线安卓系统模拟器工具是一款启动速度快,且在浏览器中就能运行流畅.你可以使用它来测试你的安卓应用,他最多能支持42种屏幕尺寸和系统版本. 长久以来,Android开发者面临的困境之一就 ...

  4. Android进阶笔记:Messenger源码详解

    Messenger可以理解为一个是用于发送消息的一个类用法也很多,这里主要分析一下再跨进程的情况下Messenger的实现流程与源码分析.相信结合前面两篇关于aidl解析文章能够更好的对aidl有一个 ...

  5. Android进阶笔记:AIDL内部实现详解 (二)

    接着上一篇分析的aidl的流程解析.知道了aidl主要就是利用Ibinder来实现跨进程通信的.既然是通过对Binder各种方法的封装,那也可以不使用aidl自己通过Binder来实现跨进程通讯.那么 ...

  6. Spring源码学习笔记12——总结篇,IOC,Bean的生命周期,三大扩展点

    Spring源码学习笔记12--总结篇,IOC,Bean的生命周期,三大扩展点 参考了Spring 官网文档 https://docs.spring.io/spring-framework/docs/ ...

  7. Android进阶笔记16:ListView篇之ListView刷新显示(全局 和 局部)

    一.ListView内容变化后,动态刷新的步骤(全局刷新): (1)更新适配器Adapter数据源:(不要使用匿名内部类) (2)调用适配器Adapter的刷新方法notifyDataSetChang ...

  8. Android进阶笔记13:ListView篇之ListView刷新显示(全局 和 局部)

    一.ListView内容变化后,动态刷新的步骤(全局刷新): (1)更新适配器Adapter数据源:(不要使用匿名内部类) (2)调用适配器Adapter的刷新方法notifyDataSetChang ...

  9. Android进阶笔记14:ListView篇之ListView性能优化

    1. 首先思考一个问题ListView如何才能提高效率 ? 当convertView为空时候,用setTag()方法为每个View绑定一个存放控件的ViewHolder对象.当convertView不 ...

随机推荐

  1. springboot+Zookeeper+Dubbo入门

    最近想学习dubbo,就利用周末写了一个特别简单的demo,不知道有没有用,先记录一下. 1.安装zookeeper并启动(安装看我上一篇博客https://www.cnblogs.com/huang ...

  2. scrapy安装和框架内容

    在cdm中:直接,pip install scrapy 有可能让你升级一下pip先,就输入这个:python -m pip install --upgrade pip 当它报错的话,看看它是缺了什么, ...

  3. nginx 代理服务指令详解

    nginx 正向代理与反向代理说明图 超级形象说明. 正向代理指令: 1, resolver 这个用于DNS服务器的ip . DNS服务器的主要工作是进行域名解析,将域名映射为对应IP地址 resol ...

  4. Android 开发手记一NDK编程实例

    在Android上,应用程序的开发,大部分基于Java语言来实现.要使用c或是c++的程序或库,就需要使用NDK来实现.NDK是Native Development Kit的简称.它是一个工具集,集成 ...

  5. 自己用 python 实现 base64 编码

    自己用 python 实现 base64 编码 base64 编码原理 二进制文件中包含有很多无法显示和打印的字符,二进制的数据一般以 ASCII 码形式(8 bit,即一个字节)存储,8 bit 可 ...

  6. Linux Tomcat 80端口 Port 80 required by Tomcat v8.5 Server at localhost is already in use.

    Port 80 required by Tomcat v8.5 Server at localhost is already in use. The server may already be run ...

  7. 【linux】dpkg 命令使用说明

    dpkg是一个debian包管理工具.能够对包进行安装.卸载.获取信息等操作.用法:    安装(解包并配置):       dpkg -i package_file       dpkg --ins ...

  8. Java线程中断的本质深入理解

    Java的中断是一种协作机制.也就是说调用线程对象的interrupt方法并不一定就中断了正在运行的线程,它只是要求线程自己在合适的时机中断自己. 一.Java中断的现象 首先,看看Thread类里的 ...

  9. 安装 VS 2015 Update 2 + Windows SDK Tools 1.3.1 + Windows SDK 10586.212 后提示找不到 10586.0 SDK 问题的解决方法

    将 Visual Studio 2015 升级到 Update 2,并安装 Windows SDK Tools 1.3.1 和 Windows SDK 10586.212 后,有可能造成原本已安装的 ...

  10. JavaScript对象 继承

    JavaScript继承主要依靠原型链实现. 原型链 利用原型让一个引用类型继承另一个引用类型水位属性和方法. 每一个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指 ...