加载流程:

if(内存命中){
     从内存中读取
}else{
     create AsyncTasks,task中的多个Runnable是通过堆栈先进后出的方式来调度,而非队列式的先进先出,目的是最先加载用户最近划到或打开的图片。    
}
 
AsyncTask:
//do in background——该后台进程在用户scroll列表的时候会暂停,从而减小了列表划动时cpu的overhead,此方法也被ImageLoader和facebook的官方app所使用。
if(磁盘缓存命中){
     从缓存中读取    
}else{
     从网络下载
  成功后,存入磁盘缓存并且存入内存
}
 
内存图片管理
LruCache,容量为1/10运行时内存。以nexus 4为例,内存2G,jvm为app分配的可用内存为512MB,那么内存中的图片LruCache大小为51.2MB。
当达到容量后,不要直接recycle bitmap,而是将bitmap加到一个WeakReference的Map中;否则在小内存手机上,很可能会recycle掉一些还被引用着的bitmap。
 
缓存图片管理
ChocolateCache,策略类似于LruCache,但是对IO读写速度和命中率都做了优化(鸣谢 伯奎)
 
下载和解析图片的注意事项
下载过程优化:
之前采用ImageLoader时,发现它先将图片下载到文件中,然后再从文件中decode图片并显示,增加了一步IO操作,所以现在直接从网络字节流decode图片并返回。
 
黑图问题:
直接从网络的InputStream解析Bitmap时,会出现黑图(图片中有横向的黑色矩形),所以不直接decode从网络得到的InputStream,而是把stream转换为一个固定长度的byte array,再进行解析,黑图问题解决。
                            // 如果不根据这个固定的length来生成byte[],而是直接decode
                            // inputstream ,会造成黑图
                            imgData = new byte[length];
 
                            byte[] temp = new byte[512];
                            int readLen = 0;
                            int destPos = 0;
 
                            while ((readLen = mInputStream.read(temp)) > 0) {
                                System.arraycopy(temp, 0, imgData, destPos, readLen);
                                destPos += readLen;
                           }
 
机型和网络兼容性问题:
三星note3在CDMA网络下得到的是GZIPInputStream(length为-1,无法采用以上方法生成byte array),其他机型和场景都是FixedLengthInputStream(length为正常大小)。所以当length=-1时,采用最基本的InputStream->OutputStream->ByteArray的方式生成图像的字节数组
 
分辨率适配问题
解析图片应采用BitmapFactory.decodeStream而不是BitmapFactory.decodeByteArray,因为后者在从source density到target density转换时,不会自动缩放。
以表情为例,某250x250的表情图片,默认的density是320,但是LG的G2手机density为480,所以此图片应按照480/320=1.5的比例放大并显示到G2手机上。但是decodeByteArray之后得到的图片长宽仍然是250x250,而如果使用decodeStream则会得到长宽均为250*1.5=375的图片,从而实现了最佳的显示效果。根本原因可以从BitmapFactory.java的源码中得到解释(第一个方法带有缩放功能,第二个方法则没有):
 
    public static Bitmap decodeStream (InputStream is, Rect outPadding, Options opts) {
       ... ...
            if (opts == null || (opts. inScaled && opts. inBitmap == null)) {
                float scale = 1.0f;
                int targetDensity = 0;
                if (opts != null) {
                    final int density = opts. inDensity;
                    targetDensity = opts. inTargetDensity;
                    if (density != 0 && targetDensity != 0) {
                        scale = targetDensity / ( float) density;//请注意这里有计算缩放比例,而decodeByteArray未进行此项操作
                    }
                }
 
                bm = nativeDecodeAsset(asset, outPadding, opts, true, scale);
                if (bm != null && targetDensity != 0) bm.setDensity(targetDensity);
 
                finish = false;
            } else {
                bm = nativeDecodeAsset(asset, outPadding, opts);
            }
        }
   ... ...
 
    public static Bitmap decodeByteArray (byte [] data, int offset, int length, Options opts) {
        if ((offset | length) < 0 || data. length < offset + length) {
            throw new ArrayIndexOutOfBoundsException();
        }
        Bitmap bm = nativeDecodeByteArray(data, offset, length, opts);
 
        if (bm == null && opts != null && opts. inBitmap != null) {
            throw new IllegalArgumentException( "Problem decoding into existing bitmap");
        }
        return bm;
    }
 
 
场景策略
网络获取的图片都是服务端处理过的图片,按原尺寸处理没有任何问题,但是本地图片或拍照图片,经常是高清大图,极易Out of memory,所以需要根据具体情况设置采样率,减小decode bitmap和write to cache时的内存占用(鸣谢 风念)
 
待优化点
关于BitmapFactory.Options.inBitmap的trade-off:
google推荐使用BitmapFactory.Options.inBitmap属性,将新的图片decode并保存到旧图片的内存(reuse the memory of old bitmaps),从而“removing both memory allocation and de-allocation”,减少GC操作,提升性能。这样做也有一个缺点,如此一来需要把从LruCache中evict出的图片放入软引用(方便用来reuse内存),而非很快就会被回收掉的弱引用,结果会造成不再使用的旧图片大量留驻内存,直到内存紧张时才被回收,虽然会提升一定性能,但是应用会“看上去”比较耗内存。
 

Android客户端中Bitmap的下载过程和缓存机制的更多相关文章

  1. wemall app商城源码Android之ListView异步加载网络图片(优化缓存机制)

    wemall-mobile是基于WeMall的android app商城,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可定制修改.本文分享wemall app商城源码Android之L ...

  2. 在android studio中导入github下载的工程

    1.从Github中下载工程压缩包,并将其解压到本地 2.修改文件 假设,解压后的文件目录如下: (1)修改配置文件  xx\build.gradle // Top-level build file ...

  3. Android开发中的输入合法性检验

    Why ? 合法性检查对于程序的健壮性具有重要作用.在Android开发中,良好的合法性检查设计机制可以使程序更加清晰,产生bug更少,交互更加友好. What ? 合法性检查的目的在于确定边界.对于 ...

  4. WCF技术剖析之八:ClientBase<T>中对ChannelFactory<T>的缓存机制

    原文:WCF技术剖析之八:ClientBase<T>中对ChannelFactory<T>的缓存机制 和传统的分布式远程调用一样,WCF的服务调用借助于服务代理(Service ...

  5. Android BLE与终端通信(三)——客户端与服务端通信过程以及实现数据通信

    Android BLE与终端通信(三)--客户端与服务端通信过程以及实现数据通信 前面的终究只是小知识点,上不了台面,也只能算是起到一个科普的作用,而同步到实际的开发上去,今天就来延续前两篇实现蓝牙主 ...

  6. Android开发中使用七牛云存储进行图片上传下载

    Android开发中的图片存储本来就是比较耗时耗地的事情,而使用第三方的七牛云,便可以很好的解决这些后顾之忧,最近我也是在学习七牛的SDK,将使用过程在这记录下来,方便以后使用. 先说一下七牛云的存储 ...

  7. ONVIF客户端中预置位设置代码实现过程

    simpleOnvif的功能:提供支持Windows.Linux.arm.Android.iOS等各种平台的SDK库,方便集成,二次开发 之前跟大家分享了我们安徽思蔷信息科技的simpleOnvif的 ...

  8. 图片以BLOB存储在后台数据库中,Android客户端要进行读取显示

    解决方法: 1:在后台以InputStream的方式将图片从数据库中读出: public static InputStream getPicInputStream(){ String id = &qu ...

  9. 【转】Android源码下载过程的一些注意事项

    原文网址:http://www.360doc.com/content/14/0113/11/11948835_344809459.shtml 其它一些事项说明: 1.在源代码下载过程中,我们在源代码下 ...

随机推荐

  1. oracle构建一致性读

    对于实际的业务系统,通常有一些热点的表,insert和delete的量非常大,这个时候就会发现一些查询语句的逻辑读比较偏高,这时可能就是oracle在构建一致性块的进行的consistent read ...

  2. .net 利用 GZipStream 压缩和解压缩

    1.GZipStream 类 此类在 .NET Framework 2.0 版中是新增的. 提供用于压缩和解压缩流的方法和属性 2.压缩byte[] /// <summary> /// 压 ...

  3. JS 利用数组拼接html字符串

    var cc = []; cc.push('<td colspan=' + fields.length + ' style="padding:10px 5px;border:0;&qu ...

  4. Centos6.4 为用户添加sudo功能

    sudo即super user do,以超级管理员的方式运行命令.使用时,只需在命令最前面加上sudo即可. 要为用户添加sudo功能,需要修改sudo的配置文件: vi /etc/sudoers ( ...

  5. Delta-wave

    Delta-wave Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...

  6. [置顶]Win2012R2的一个Bug安装群集后可能引发的软件崩溃问题及相应补丁

    [置顶]Win2012R2的一个Bug安装群集后可能引发的软件崩溃问题及相应补丁 如标题,笔者查阅资料发现微软声称安装故障转角色后就可能发生上述描述问题,但不止于SSMS崩溃.建议使用win2012R ...

  7. C#面向对象的三大特征

    一,封装:我们可以把世界上任何一个东西都看作为一个对象,那么我们这里以人为例,一个人就肯定是一个对象了.那么封装是什么呢?封装就是这个人要完成一件事情,他所需要的任何工具都带在了自己的身上,所需要的技 ...

  8. 怎样安装Joomla 1.7网站系统

    http://jingyan.baidu.com/article/8065f87fc3de112331249830.html   如果你想使用Joomla(地球上最好的内容管理系统之一)搭建一个网站, ...

  9. poj 2406 Power Strings【最小循环节】

    Power Strings Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 36926   Accepted: 15254 D ...

  10. Code Forces 711D Directed Roads

    D. Directed Roads time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...