加载流程:

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. 关于Json传递的日期/Date(数字)/解析

    在将DateTime类型的数据Json后传到前台展示,出现如下效果 ,在客户端如何解析呢?在jquery easyui 的字段中加一个格式化的函数调用.   { field: 'CreateTime' ...

  2. android Service开机启动及debug

    开机启动一个service需要做的工作如下: 1.开发一个receiver用于接收系统广播: public class BootReceiver extends BroadcastReceiver { ...

  3. bzoj1085

    肯定是搜索题无疑问, 首先要求在15步以内(包括15步)到达目标状态,也就是限定了搜索的深度,于是我们用dfs更合适 但这样复杂度仍然太大,原因就是我们在搜索中做了很多很不优的尝试 考虑当前状态若与目 ...

  4. bzoj2705

    一个常用的结论(方法) 只要知道gcd(i,n)=L 的i的个数s,我们就能很轻易得出答案 gcd(i,n)=L gcd(i/L,n/L)=1 不难得到这样的s=与n/L互质的个数=phi(n/L) ...

  5. 【转】关于Certificate、Provisioning Profile、App ID的介绍及其之间的关系

    原文网址:http://www.cnblogs.com/cywin888/p/3263027.html 刚接触iOS开发的人难免会对苹果的各种证书.配置文件等不甚了解,可能你按照网上的教程一步一步的成 ...

  6. Base64上传图片

    #region 上传图片 [HttpPost]/// <summary>/// 上传文件 jpg图片/// </summary>/// <param name=" ...

  7. 计算几何(凸包模板):HDU 1392 Surround the Trees

    There are a lot of trees in an area. A peasant wants to buy a rope to surround all these trees. So a ...

  8. Leveraging the Power of Asynchrony in ASP.NET [转]

    Asynchronous programming has had a lot of attention in the last couple of years and there are two ke ...

  9. ManagerDay-1

    初做管理,没有任何管理经验的我,有点紧张,在来公司之前,脑子里一直在想能不能胜任这份工作. 想着能否做出合格的流程图,像样的需规.我该如何和组内开发人员打好交道.报价预算该如何做,这些都交织在脑内显得 ...

  10. 记录一次MVC3升级MVC4遇到的问题

    前些天,项目组将项目从mvc3升级至mvc4,完了之后,发现突然涌现出一大堆问题.主要是在前端,Razor引擎升级导致的. Razor是从mvc3开始引入的,用过mvc2的就会知道,Razor用起来确 ...