开发者社区> 一叶飘舟> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

ListView异步加载图片(解决图片混淆)

简介:
+关注继续查看
代码下载地址:
http://115.com/file/e75ks6jj#ImageLoader_test.zip




       由于工作原因,很久没有写博客了,工作中经常遇到ListView异步加载图片的问题,国内的网站上查了N多资料,几乎没有一个可用的,最根本的图片混淆问题都没有得到充分地解决。我的这个例子是借鉴Google Code中的例子,删除了其中的没有必要的代码,完全可行。
 
该工程由ImageListActivity、ImageAdapter、ImageDownloader三个类构成。前两个类比较简单,这里不再赘述,下面我们就来分析一下ImageDownloader究竟是如何做到避免图片混淆的。
 
    public void download(String url, ImageView imageView) {
        resetPurgeTimer(); //清空集合
        Bitmap bitmap = getBitmapFromCache(url);
 
        if (bitmap == null) {
            forceDownload(url, imageView);
        } else {
            cancelPotentialDownload(url, imageView);
            imageView.setImageBitmap(bitmap);
        }
}
 
通过研究以上代码可知,真正的下载代码是由forceDownload方法来完成,该方法如下:
 
private void forceDownload(String url, ImageView imageView) {
    // State sanity: url is guaranteed to never be null in 
     //  DownloadedDrawable and cache keys.
    if (url == null) {
         imageView.setImageDrawable(null);
         return;
    }
 
if (cancelPotentialDownload(url, imageView)) {
BitmapDownloaderTask task = new BitmapDownloaderTask(imageView)
DownloadedDrawable downloadedDrawable = 
                        new DownloadedDrawable(task);
imageView.setImageDrawable(downloadedDrawable);
task.execute(url);
}
 
 
}
用便于理解的语言可以这样解释:
if(取消了之前该imageView对应的图片下载) {
       1.创建下载图片的Task:BitmapDownloaderTask。
         (让BitmapDownloaderTask 拥有imageView的引用,实现二者之           间的绑定,既该imageView一一对应一个BitmapDownloaderTask 对象)
 
       2.初始化每一个ImageView为默认图片或颜色。(该默认图片就是DownloadedDrawable,该DownloadedDrawable拥有BitmapDownloaderTask 的引用,实现二者之间的绑定,既该DownloadedDrawable一一对应一个BitmapDownloaderTask 对象)
 
       3.启动下载任务
}
 
有些童鞋对cancelPotentialDownload可能理解的不是很透彻。
   private static boolean cancelPotentialDownload(String url, 
                                               ImageView imageView) {
        BitmapDownloaderTask bitmapDownloaderTask = 
                        getBitmapDownloaderTask(imageView);
 
        if (bitmapDownloaderTask != null) {
            String bitmapUrl = bitmapDownloaderTask.url;
            if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
                bitmapDownloaderTask.cancel(true);
            } else {
                // The same URL is already being downloaded.
                return false;
            }
        }
           
        return true;
}
 
该方法对于,刚刚进入页面在没有做任何操作(尤其是滑动)时或者说对于listview中任何一个item首次加载时,当然是返回true,因为这个时候bitmapDownloaderTask为null.这时就会首次去执行下载图片的任务。
但是当我们向下滑动一屏,再向上滑动回之前那一屏时,这个时候bitmapDownloaderTask 已不再为null. 我们将bitmapDownloaderTask.url与参数中的url进行对比(这个时候注意:很明显参数中的url才是我们需要下载的url):如果不等,则停止正在下载的(因为这不是我们需要的),返回true;如果相等,则返回false,继续当前的图片下载任务。


 
 
这时候,又有童鞋问了,为什么以上imageView对应的url会变呢?
别着急,上下滑动listview,请查看ImageAdapter类中getView方法打印出来的Log, 如下图:






再看看getView方法:
public View getView(int position, View view, ViewGroup parent) { 
if (view == null) { 
view = new ImageView(parent.getContext());
view.setPadding(6, 6, 6, 6); 
view.setMinimumHeight(150); 
view.setMinimumWidth(150); 
Log.v(TAG, "getView, ==========new========pos: "  
           + position + " ,view: " + view); 
} else { 
Log.v(TAG, "getView, pos: " + position + " ,view: " + view); 
}
 
imageDownloader.download(URLS[position], (ImageView) view); 
return view; 
}


怎么样,观察标记,有什么想法没。这说明当进入listView页面时,如手机一屏只能显示6个item,那么android系统就初始化6个view,当上下滑动时,android系统会重用这些已经创建好的ImageView,改变的仅仅是ImageView所显示的图片。


下面我们就对第一屏的最顶上的一个ImageView(以下取名为A)进行分析:
我们在第一屏首次构建了A,并绑定了一个BitmapDownloaderTask,当用手指下滑至A消失时,这时肯定会露出一个新的item,该item就会重用之前的A。这时,如果取出之前消失的A对应的task,我们对比task.url与参数中的url,如果不等,那么就暂停没有消失时正在下载的url(因为已经滑过去了,既不可见,再下载就没有意义了,再说优先级更高的应该是当前可见部分图片的下载)。


之后我们又调用了
DownloadedDrawable downloadedDrawable = new DownloadedDrawable(task);
imageView.setImageDrawable(downloadedDrawable);
在下载图片之前,需要先给ImageView设置默认的图片.以上两句很重要,否则就不能做到真正的图片混淆。


我查了很多资料,国内资料上做的最好的也就是该例子去掉以上两句的效果,会先闪一下错误的图片,而后再显示正确的图片。


以下是我收录的比较好的更新ListView的文章,在这里分享给大家:
 
1. code google(最好的实现实例)
2. Android ListView 异步加载图片 再优化
3. 滑动过程中不加载图片
4. 更新ListView的一个Item

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
android中ListView异步加载图片时的图片错位问题解决方案
android中ListView异步加载图片时的图片错位问题解决方案
0 0
listview异步加载图片并防止错位
android listview 异步加载图片并防止错位 网上找了一张图, listview 异步加载图片之所以错位的根本原因是重用了 convertView 且有异步操作. 如果不重用 convertView 不会出现错位现象, 重用 convertView 但没有异步操作也不会有问题。 我简单分析一下: 当重用 convertVie
938 0
解决ListView异步加载网络图片的各种问题(二)
MainActivity如下: package lee.listviewimage; import java.util.ArrayList; import java.
763 0
解决ListView异步加载网络图片的各种问题(一)
MainActivity如下: package com.example.testlistview; import java.util.ArrayList; import android.
706 0
Android Glide加载网络图片不显示,但用网页打开又正常显示
Android Glide加载网络图片不显示,但用网页打开又正常显示
0 0
+关注
文章
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载