技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> Android开发 --> 对Android中的多图片异步加载的重新思考

对Android中的多图片异步加载的重新思考

浏览:1370次  出处信息

现在想来,Android SDK把并行执行改为串行执行也并不无道理。

起因

不知道大家有没有发现,在2.0.4.1(37)版本之前的开源中国客户端首次加载图片的时候,会很慢,尤其是动弹列表中的图片。甚至网速慢的时候感觉图片根本加载不出来。

原因是在下载网络图片的时候使用了多线程并发执行的方式,什么意思呢,也就是开启了多个线程同时去下载多张图片。按照正常的思维来想,做图片加载操作使用多线程,这应该是很正常的,因为在我们的思维中,多线程资源利用率更高,程序响应更快。

举个例子:一个应用程序需要从本地文件系统中读取和处理文件的情景。比方说,从磁盘读取一个文件需要5秒,处理一个文件需要2秒。处理两个文件则需要

  5秒读取文件A
  2秒处理文件A
  5秒读取文件B
  2秒处理文件B
---------------------
  总共需要14秒

从磁盘中读取文件的时候,大部分的CPU时间用于等待磁盘去读取数据。在这段时间里,CPU非常的空闲。它可以做一些别的事情。通过改变操作的顺序,就能够更好的使用CPU资源。看下面的顺序

  5秒读取文件A
  5秒读取文件B + 2秒处理文件A
  2秒处理文件B
---------------------
  总共需要12秒

CPU等待第一个文件被读取完。然后开始读取第二个文件。当第二文件在被读取的时候,CPU会去处理第一个文件。记住,在等待磁盘读取文件的时候,CPU大部分时间是空闲的。总的说来,CPU能够在等待IO的时候做一些其他的事情。这个不一定就是磁盘IO。它也可以是网络的IO,或者用户输入。通常情况下,网络和磁盘的IO比CPU和内存的IO慢的多。

既然采用多线程并发执行可以提高CPU的利用率,可是为什么反倒用在Android的图片加载上变得更慢了?

看到这里,你应该已经想到原因了。就好像我们写代码,一个人同时写两个Android应用,并发布上线。假设应用发布不需要上线审核,且A与B的功能几乎相同。如果我们去先写应用A的一个功能,当A某一个功能写完的时候再去写应用B相同的功能,那么写起来自然是要快很多。这就是并发执行,同时去执行A与B。但是这样A与B完成的总时间是缩短了,可以单个A应用完成的时间却被拉长了。因为写到一半的时候被迫去完成B应用。

所以这也是为什么你会发现37版本之前的OSC客户端图片几乎是同时出来的。

回到Android上,我之前的博客曾讲过:AsyncTask在android2.3的时候线程池是一个核心数为5线程,队列可容纳10线程,最大执行128个任务,这存在一个问题,当你真的有138个并发时,即使手机没被你撑爆,那么超出这个指标应用绝对crash掉。 后来升级到3.0,为了避免并发带来的一些列问题,AsyncTask竟然成为序列执行器了,也就是你即使你同时execute N个AsyncTask,它也是挨个排队执行的。 这一点请同学们一定注意,AsyncTask在3.0以后,是异步的没错,但不是并发的。不知道的同学可以去看看《Thread并发请求封装——深入理解AsyncTask类》《一套完善的Android异步任务类》

现在想来,Android SDK把并行执行改为串行执行也并不无道理。

也许你会担心,那改回串行以后会不会又出现同时加载129个图片的时候崩溃的问题。当然,是不会的。在图片加载的时候已经做了下载任务取消的设计,在listView中加载图片的时候,如果滚动出这一屏,图片的下载任务会马上停止,而去加载新的图片下载。总不会一个屏幕就显示129张图吧。

/**
 * 取消一个下载请求
 *
 * @param view
 */
public void cancle(View view) {
  for (BitmapWorkerTask task : taskCollection) {
    if (task.imageView.equals(view)) {
    task.cancelTask();
    taskCollection.remove(task);
    break;
    }
  }
}

建议继续学习:

  1. 关于IO的同步,异步,阻塞,非阻塞    (阅读:14485)
  2. fsockopen 异步处理    (阅读:9034)
  3. 配合jquery实现异步加载页面元素    (阅读:5375)
  4. 使用django+celery+RabbitMQ实现异步执行    (阅读:5023)
  5. 异步编程与响应式框架    (阅读:3913)
  6. 多核与异步并行    (阅读:3898)
  7. redis源代码分析 - event library    (阅读:3177)
  8. Google Analytics 异步代码详解    (阅读:3169)
  9. 异步完成后新开窗口    (阅读:2953)
  10. php的异步http请求类    (阅读:2924)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1