Android客户端中Bitmap的下载过程和缓存机制

加载流程:

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读写速度和命中率都做了优化(鸣谢 伯奎)

下载和解析图片的注意事项

黑图问题:

// 如果不根据这个固定的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),其他机型和场景都是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的图片,从而实现了最佳的显示效果。

根本原因详见源码:

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;

}

场景策略

网络图片按原尺寸处理

本地图片或拍照图片,因为经常是高清大图,所以需要根据具体情况设置采样率,减小decode bitmap和write to cache时的内存占用(鸣谢 风念)

Android客户端中Bitmap的下载过程和缓存机制,布布扣,bubuko.com

时间: 2024-10-05 05:01:46

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

Android之ListView异步加载网络图片(优化缓存机制)【转】

网上关于这个方面的文章也不少,基本的思路是线程+缓存来解决.下面提出一些优化: 1.采用线程池 2.内存缓存+文件缓存 3.内存缓存中网上很多是采用SoftReference来防止堆溢出,这儿严格限制只能使用最大JVM内存的1/4 4.对下载的图片进行按比例缩放,以减少内存的消耗 具体的代码里面说明.先放上内存缓存类的代码MemoryCache.java: public class MemoryCache { private static final String TAG = "MemoryCa

Android之ListView异步加载网络图片(优化缓存机制)

网上关于这个方面的文章也不少,基本的思路是线程+缓存来解决.下面提出一些优化: 1.采用线程池 2.内存缓存+文件缓存 3.内存缓存中网上很多是采用SoftReference来防止堆溢出,这儿严格限制只能使用最大JVM内存的1/4 4.对下载的图片进行按比例缩放,以减少内存的消耗 具体的代码里面说明.先放上内存缓存类的代码MemoryCache.java: [java] view plain copy public class MemoryCache { private static final

Android客户端多文件上传

在web开发中,多文件上传时是非常方便的,直接使用Http协议提交数据即可.格式如下: <FORM METHOD=POST ACTION="http://192.168.1.101:8083/upload/servlet/UploadServlet" enctype="multipart/form-data"> <INPUT TYPE="text" NAME="name"> <INPUT TYPE

WCF技术剖析之八:ClientBase&lt;T&gt;中对ChannelFactory&lt;T&gt;的缓存机制

原文:WCF技术剖析之八:ClientBase<T>中对ChannelFactory<T>的缓存机制 和传统的分布式远程调用一样,WCF的服务调用借助于服务代理(Service Proxy).而ChannelFactory<T>则是服务代理的创建者.WCF采用基于终结点(Endpoint)服务消费方式:WCF服务通过一个或者多个终结点暴露给潜在的服务消费者,服务的消费中通过与之匹配的终结点与之交互.在客户端,我们具有两种典型的服务代理创建方式,其一是通过诸如SvcUti

(原创)优酷android客户端 下载中 bug 解决

在网络情况不好的情况下,优酷android客户端下载视频会终止,用户放弃下载点击 删除该任务以后,切换到网络好的情况下进行下载,会显示该视频已在下载队列里,然后客户端UI界面却什么都看不到.导致用户根本无法下载. 其实优酷的下载都是使用读文件形式的 在优酷android的文件目录那里,(目前不考虑挂在SD卡和其他存储优化)就是内存设备/youku/offinedata里有很多下载视频的文件夹,里面有文件夹创建的时间.图片.flv形式的分集.info文件.youku.m3u8文件 下载信息(包括下

Android客户端单线程下载

具体效果如上图所示,具体操作步骤如: 1.先新建一个工程名为getDataInternet的应用: 2.修改res/values中的string.xml文件,具体代码如下: 1 <?xml version="1.0" encoding="utf-8"?> 2 <resources> 3 4 <string name="app_name">Android客户端单线程下载</string> 5 <

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

Android开发中的图片存储本来就是比较耗时耗地的事情,而使用第三方的七牛云,便可以很好的解决这些后顾之忧,最近我也是在学习七牛的SDK,将使用过程在这记录下来,方便以后使用. 先说一下七牛云的存储原理,上面这幅图片是官方给出的原理图,表述当然比较清晰了.可以看出,要进行图片上传的话可以分为五大步: 1. 客户端用户登录到APP的账号系统里面: 2. 客户端上传文件之前,需要向业务服务器申请七牛的上传凭证,这个凭证由业务服务器使用七牛提供的服务端SDK生成: 3. 客户端使用七牛提供的客户端S

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

解决方法: 1:在后台以InputStream的方式将图片从数据库中读出: public static InputStream getPicInputStream(){ String id = "f304733361e243779b2340afe20e62bf"; Connection conn = JdbcUtil.getConnection(); PreparedStatement ps = null; ResultSet rs = null; InputStream is = n

浅谈Android和java中的多线程下载

为什么要使用多线程下载呢? 究其原因就一个字:"快",使用多线程下载的速度远比单线程的下载速度要快,说到下载速度,决定下载速度的因素一般有两个: 一个是客户端实际的网速,另一个则是服务端的带宽.我们经常使用的是单线程下载,也就是下载一个文件就是开启一个线程去请求下载资源. 这里我们不考虑客户端实际网速因素,因为这个因素多变,不好控制.我们主要考虑的因素就是服务端的带宽.那么服务端是如何给每个客户端分配 它的下载带宽的呢???它分配的原理大致是这样的,服务端只会给请求它的每个线程平均分配