收藏 分享(赏)

Android 图片加载性能优化总结.docx

上传人:yjrm16270 文档编号:6278618 上传时间:2019-04-04 格式:DOCX 页数:54 大小:499.70KB
下载 相关 举报
Android 图片加载性能优化总结.docx_第1页
第1页 / 共54页
Android 图片加载性能优化总结.docx_第2页
第2页 / 共54页
Android 图片加载性能优化总结.docx_第3页
第3页 / 共54页
Android 图片加载性能优化总结.docx_第4页
第4页 / 共54页
Android 图片加载性能优化总结.docx_第5页
第5页 / 共54页
点击查看更多>>
资源描述

1、Android 图片加载性能优化总结一、Android Bitmap 加载大尺寸图片优化: 压缩原因:1.imageview 大小如果是 200*300 那么加载个 2000*3000 的图片到内存中显然是浪费可耻滴行为;2.最重要的是图片过大时直接加载原图会造成 OOM 异常(out of memory 内存溢出)所以一般对于大图我们需要进行下压缩处理看不懂英文的话木有关系,本篇会有介绍主要处理思路是:1.获取图片的像素宽高( 不加载图片至内存中,所以不会占用资源)2.计算需要压缩的比例3.按将图片用计算出的比例压缩,并加载至内存中使用官网大图片加载教程(上面网址里的)对应代码就是:/* 获

2、取压缩后的图片* param res* param resId* param reqWidth 所需图片压缩尺寸最小宽度* param reqHeight 所需图片压缩尺寸最小高度* return*/public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) / 首先不加载图片 ,仅获取图片尺寸final BitmapFactory.Options options = new BitmapFactory.Options();/ 当 inJu

3、stDecodeBounds 设为 true 时,不会加载图片仅获取图片尺寸信息options.inJustDecodeBounds = true;/ 此时仅会将图片信息会保存至 options 对象内,decode 方法不会返回bitmap 对象BitmapFactory.decodeResource(res, resId, options);/ 计算压缩比例 ,如 inSampleSize=4 时,图片会压缩成原图的 1/4options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);/ 当 inJus

4、tDecodeBounds 设为 false 时,BitmapFactory.decode.就会返回图片对象了options. inJustDecodeBounds = false;/ 利用计算的比例值获取压缩后的图片对象return BitmapFactory.decodeResource(res, resId, options);代码详解:核心方法是 BitmapFactory.decode.(, options).的意思是此外还有一系列的 decodeFile/decodeStream 等等方法,都是利用options 灵活解析获取图片 ,只不过解析图片的来源不同罢了,比如网络图片获取,

5、一般就是解析字节流信息然后decode 获取图片实例Options 是图片配置信息,参数详细介绍下:inJustDecodeBounds 是否只解析边界设为 true 时去 decode 获取图片,只会加载像素宽高信息设为 false 时 decode 则会完全加载图片inSampleSize 压缩比例比如原图 200*300,如果值是 2 时会压缩成 100*150; 是 4 则图片压缩成50*75 最好是 2 的幂数,比如 2 4 8 16 .outHeight 图片原高度outWidth 图片原宽度其他参数自行研究,这里暂时只用到这几个decodeSampledBitmapFromRes

6、ource 方法内的三段代码对应上面的三步流程难点在于中间那步,压缩比例的计算, 官网同样提供了个 calculateInSampleSize 方法其中 reqWidth 和 reqHeight 是所需图片限定最小宽高值/* 计算压缩比例值* param options 解析图片的配置信息* param reqWidth 所需图片压缩尺寸最小宽度* param reqHeight 所需图片压缩尺寸最小高度* return*/public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, i

7、nt reqHeight) / 保存图片原宽高值final int height = options. outHeight;final int width = options. outWidth;/ 初始化压缩比例为 1int inSampleSize = 1;/ 当图片宽高值任何一个大于所需压缩图片宽高值时,进入循环计算系统if (height reqHeight | width reqWidth) final int halfHeight = height / 2;final int halfWidth = width / 2;/ 压缩比例值每次循环两倍增加,/ 直到原图宽高值的一半除以压

8、缩值后都大于所需宽高值为止while (halfHeight / inSampleSize) = reqHeightreturn inSampleSize;利用此方法获取到所需压缩比例值,最终获取到压缩后的图片以上代码能够看懂的话,下面这段/*扯淡*/ 可以跳过逻辑是将原图宽高一半一半的缩减,一直减到宽高都小于自己设定的限定宽高时为止,测试的时候问题来了原图 400*300,我限定值 200*150,if 满足进入,while 循环第一次,400/2/1=200 不满足 的条件结束循环,最终返回了个 inSampleSize=1 给我马丹我限定值正好是原图的一半啊,你应该返回给我 2 啊你特么

9、最后返回个 1 给我,那压缩处理后的图还是 400*300!当我将限定值稍微改一下变成 195*145 稍微降低一点点时 if 满足进入,while 循环第一次,400/2/1195 满足 然后压缩比例 1*2 变成了 2,在下一次 while 循环时不满足条件结束,最后返回比例值 2 满足压缩预期官网的这个方法是: 将图片一半一半的压缩, 直到压缩成成大于所需宽高数的那个最低值大于 不是大于等于,所以就会出现我上面那种情况, 我觉得方法不是太好 = = 能满足压缩的需求,但是压缩的比例不够准确所以最好改成大于等于,如下( 个人意见,仅供参考,在实际压缩中很少遇到恰巧等于的这个情况,所以 和=

10、 差别也不大额看我这扯扯淡就当对计算比例的逻辑加深个理解吧)while (halfHeight / inSampleSize) = reqHeight优化:还是上面例子,如果限定了 200*150,而原图是 390*290 会是个啥情况?还是第一次 while 循环,390/2/1 结果是 195 不满足200 的情况,结束循环, 比例值为 1,最后图片压缩成 400*300虽然压缩一次以后没有满足大于所需宽高,但是和所需宽高很接近啊!能不能做一个获取压缩成最接近所需宽高数的比例值呢?我也不知道= = 回头可以慢慢研究, 这个“接近“ 的定义比较模糊,不好掌握找了几个有名的图片加载开源框架发现

11、也都没有这种处理- -不知道是这样设计是不需要呢,还是没啥用呢以上,图片的像素大小已经做了缩放, 但是图片的大小除了和像素有关, 还和色彩样式有关不同的样式决定了图片单个像素占的字节数比如,图片默认的色彩样式为 ARGB_8888,每个像素占 4byte(字节)大小可以看到一共有四种色彩样式ALPHA_8 每个像素只要 1 字节可惜只能代表透明度, 没有颜色属性ARGB_4444 每个像素要 2 字节带透明度的颜色可惜官方不推荐使用了ARGB_8888 每个像素要 4 字节带透明度的颜色, 默认色样RGB_565 每个像素要 2 字节 不带透明度的颜色默认为 ARGB_8888,如果想丧心病狂

12、的继续减少图片所占大小不需要透明度参数的话,那就可以把色彩样式设为 RGB_565设置方法是在 BitmapFactory.decode获取图片事例时修改配置参数的 inPreferredConfig 参数opts.inPreferredConfig = Bitmap.Config. RGB_565 ;想亲自撸一撸试一试压缩图片了吧?要注意点问题,如果用 res 包下图片测试的话, 你会发现有图片尺寸有点混乱那是因为在 drawable-*dpi 文件夹中的图片会根据对应对应的屏幕密度值不同自动进行一定的缩放,比如放在 drawable-hdpi 里的图片, 直接不经过压缩 BitmapFac

13、tor.decode出来,会发现 bitmap 的宽高值是原图的 2/3,测试的时候图片记得放在 drawable 包下(没有的话自己 res 下新建一个),否则你会被奇怪的宽高值弄凌乱的,具体变化原因参考源代码处理,或者网上搜搜看。还有就是 BitmapFactory.decodeStream 方法会偶尔解析图片失败(好像是安卓低版本的一个 bug),此时推荐做法是将流转换为字节流处理,然后利用decodeByteArray 方法获取图片。二、Android 加载多张图片的缓存处理一般少量图片是很少出现 OOM 异常的,除非单张图片过大 那么就可以用教程一里面的方法了通常应用场景是 list

14、view 列表加载多张图片,为了提高效率一般要缓存一部分图片,这样方便再次查看时能快速显示不用重新下载图片但是手机内存是很有限的当缓存的图片越来越多, 即使单张图片不是很大, 不过数量太多时仍然会出现 OOM 的情况了本篇则是讨论多张图片的处理问题图片缓存的一般处理是1.建立一个图片缓存池, 用于存放图片对应的 bitmap 对象2.在显示的时候, 比如 listview 对应适配器的 getView 方法里进行加载图片的工作, 先从缓存池通过 url 的 key 值取,如果取到图片了直接显示,如果获取不到再建立异步线程去下载图片(下载好后同时保存至图片缓存池并显示 )但是缓存池不能无限大啊不

15、然就会异常了, 所以通常我们要对缓存池进行一定控制需要有两个特性: 总大小有个限制,不然里面存放无限多的图片时会内存溢出 OOM 异常当大小达到上限后,再添加图片时,需要线程池能够智能化的回收移除池内一部分图片,这样才能保证新图片的显示保存异步线程下载图片神马的简单,网上异步下载任务的代码一大堆 ,下载以后流数据直接decode 成 bitmap 图片即可难点在与这个图片缓存池的设计,现在网上的实现主要有两种1.软引用/弱引用2.LruCache-拓展: java 中 4 种引用分类强引用平常使用的基本都是强引用,除非主动释放(图片的回收,或者=null 赋值为空等),否则会一直保存对象到内存

16、溢出为止软引用 SoftReference在系统内存不够时,会自动释放部分软引用所指对象弱引用 WeakReference系统偶尔回收扫描时发现弱引用则释放对象,即和内存够不够的情况无关 ,完全看心情虚引用不用了解,其实我也不熟悉框架基本都比较爱用这个软应用保存图片作为缓存池,这样在图片过多不足时 ,就会自动回收部分图片,防止 OOM但是有缺点,无法控制内存不足时会回收哪些图片 ,如果我只想回收一些不常用的 ,不要回收常用的图片呢?于是引入了二级缓存的逻辑即设置两个缓存池,一个强引用 ,一个软引用, 强引用保存常用图片,软应用保存其他图片强引用因为不会自动释放对象,所以大小要进行一定限定,否则

17、图片过多会异常, 比如控制里面只存放 10 张图片,然后每次往里面添加图片的时候,检查如果数量超过 10 张这个阀值,临界点值时,就移除强引用里面最不常用的那个图片,并将其保存至软应用缓存池中整个缓存既作为一个整体(一级二级缓存都是内存缓存 每次显示图片前都要检查整个缓存池中有没有图片)又有一定的区分(只回收二级缓存软引用中图片 ,不回收一级缓存中强引用的图片)代码实现软应用缓存池类型作为二级缓存: HashMap mSecondLevelCache = new HashMap();强引用作为一级缓存,为了实现删除最不常用对象,可以用 LinkedHashMap 类LinkedHashMap

18、对象可以复写一个 removeEldestEntry,这个方法就是用来处理删除最不常用对象逻辑的按照之前的设计就可以这么写:final int MAX_CAPACITY = 10; / 一级缓存阈值/ 第一个参数是初始化大小/ 第二个参数 0.75 是加载因子为经验值/ 第三个参数 true 则表示按照最近访问量的高低排序,false 则表示按照插入顺序排序 HashMap mFirstLevelCache = new LinkedHashMap( MAX_CAPACITY / 2, 0.75f, true) / eldest 最老的对象,即移除的最不常用图片对象/ 返回值 true 即移除该

19、对象,false 则是不移除protected boolean removeEldestEntry(Entry eldest) if (size() MAX_CAPACITY) / 当缓存池总大小超过阈值的时候,将老的值从一级缓存搬到二级缓存 mSecondLevelCache.put(eldest.getKey(), new SoftReference(eldest.getValue(); return true; return false; ; 每次图片显示时即使用时,如果存在与缓存中,则先将对象从缓存中删除,然后重新添加到一级缓存中的最前端会有三种情况1.如果图片是从一级缓存中取出来的,

20、则相当于把对象移到了一级缓存池的最前端(相当于最近使用的一张图片)2.如果图片是从二级缓存中取出来的,则会存到一级缓存池最前端并检测, 如果超过阀值,则将最不常用的一个对象移动到二级缓存中3.如果缓存中没有, 那就网上下载图片,下载好以后保存至一级缓存中 ,同样再进行检测是否要移除一个对象至二级缓存中结合现实例子理解下(如果以上逻辑了解可以跳过) :美国篮球,比如有一个最高水平的联赛 NBA,还有一个次一级的联赛 NBDL一级联赛 NBA 的排名按最近一次拿冠军的时间由近到远排列 ,我们规定,每一季度比赛都要产生一个冠军,冠军可能是已有的任何一个队伍也可能是一个民间来的新队伍而当一个队伍获取冠

21、军的时候就给他加到一级队伍 NBA 里 由于是最近一次拿冠军,所以加进去的时候也是排名第一NBA 作为最高水平,我们对数量是有限制的,所以每次有新冠军产生的时候我们都做一次检测,如果队伍总数量超过 20 支,那么就移除排名最低即离上次获冠军时间最长的那个最差队伍.如果每季度比赛拿冠军相当于一次图片使用操作,那上面三种情况就对应我们例子中的 :1.NBA 的队伍拿冠军,相当于这个队伍排名变成了第一名但 NBA 队伍总数不变, 没有新加入来的2.NBDL 二级联赛拿冠军,则加入到 NBA 里面,且变成了第一名 由于 NBA 队伍相当于增加了一个,那就要检测一下是否超过 20 支并将最差成绩的挤到

22、NBDL 中3.民间来大神了虐了全部的队伍拿了冠军,那直接加入 NBA 然后变成第一名,同样, 检测 NBA球队数量判断是否要挤出去一队NBDL 球队相当于软应用的二级缓存池 , 不限定数量 多少都可以, 直到美国篮联维护全部NBA NBDL 球队的资金不够了 (相当于图片过多应用内存不足了)则自动解散一部分球队,落入民间,直到下一次获取总冠军再加入进来(相当于图片从缓存中移除了,下次使用要重新下载)那 NBA 就相当于一级缓存,经常拿冠军(相当于高频率使用的图片 ),那我们就不想因为资金不足随机解散几个球队恰好就解散了 NBA 队伍,则规定资金不够时只解散二级联赛 NBDL 的队伍因为他们获

23、取比赛几率低一点民间队伍存在与联赛系统之外(相当于不存在缓存中的图片 ), 而任何一个 NBA NBDL 联赛球队我们都可以理解为都是民间晋级过来的只不过从民间获取总冠军并加入联赛需要一个取名字啊登记啊等等的办手续过程(下载图片),比较麻烦,所以我们要尽可能的少办手续而联赛队伍(包括 NBA NBDL)获取总冠军则不需要麻烦的手续,可以直接参加比赛去拿冠军(直接获取显示)两个联赛,一个常用的限定数量,一个不常用的不限定数量,但是资金不足时自动回收部分二级球队相当于图片的二级缓存Disk 缓存可以简单的理解为将图片缓存到 sd 卡中由于内存缓存在程序关闭第二次进入时就清空了,对于一个十分常用的图

24、片比如头像一类的我们希望不要每次进入应用都重新下载一遍,那就要用到 disk 缓存了,直接图片存到了本地,打开应用时直接获取显示网上获取图片的大部分逻辑顺序是内存缓存中获取显示(强引用缓存池 -弱引用缓存池) - 内存中找不到时从 sd 卡缓存中获取显示 - 缓存中都没有再建立异步线程下载图片,下载完成后保存至缓存中按照获取图片获取效率的速度,由快到慢的依次尝试几个方法以文件的形式缓存到 SD 卡中 ,优点是 SD 卡容量较大,所以可以缓存很多图片, 且多次打开应用都可以使用缓存,缺点是文件读写操作会耗费一点时间,虽然速度没有从内存缓存中获取速度快,但是肯定比重新下载一张图片的速度快 而且还不

25、用每次都下载图片浪费流量所以使用优先级就介于内存缓存和下载图片之间了注意:sd 卡缓存一般要提前进行一下是否装载 sd 卡的检测, 还要检测 sd 卡剩余容量是否够用的情况程序里也要添加注明相应的权限使用 LruCache 处理图片缓存以上基本完全掌握了,每一张图最好再进行一下教程(一) 里面介绍的单张缩放处理, 那基本整个图片缓存技术就差不多了但随着 android sdk 的更新,新版本其实提供了更好的解决方案, 下面介绍一下摘取段对软引用的介绍Avoid Soft References for CachingIn practice, soft references are ineffic

26、ient for caching. The runtime doesnt have enough information on which references to clear and which to keep. Most fatally, it doesnt know what to do when given the choice between clearing a soft reference and growing the heap.The lack of information on the value to your application of each reference

27、 limits the usefulness of soft references. References that are cleared too early cause unnecessary work; those that are cleared too late waste memory.Most applications should use an android.util.LruCache instead of soft references. LruCache has an effective eviction policy and lets the user tune how

28、 much memory is allotted.简单翻译一下我们要避免用软引用去处理缓存 在实践中,软引用在缓存的处理上是没有效率的。运行时没有足够的信息用于判断哪些引用要清理回收还有哪些要保存。最致命的,当同时面对清理软引用和增加堆内存两种选择时它不知道做什么。 对于你应用的每一个引用都缺乏有价值的信息,这一点限制了软引用让它的可用性十分有限。过早清理回收的引用导致了无必要的工作; 而那些过晚清理掉的引用又浪费了内存。大多数应用程序应该使用一个 android.util。LruCache 代替软引用。LruCache 有一个有效的回收机制,让用户能够调整有多少内存分配。简而言之,直接使用软

29、引用缓存的话效果不咋滴推荐使用 LruCachelevel12 以后开始引入的 ,为了兼容更早版本,android-support-v4 包内也添加了一个LruCache 类,所以在 12 版本以上用的话发现有两个包内都有这个类,其实都是一样的那么这个类是做啥的呢这里是官方文档http:/ 的意思是 Least Recently Used 即近期最少使用算法眼熟吧,其实之前的二级缓存中的那个强引用 LinkedHashMap 的处理逻辑其实就是一个LRU 算法而我们查看 LruCache 这个类的源代码时发现里面其实也有一个 LinkedHashMap,大概扫了眼,逻辑和我们之前自己写的差不多

30、核心功能基本都是: 当添加进去新数据且达到限制的阀值时,则移除一个最少使用的数据根据这个新的类做图片加载的话,网上大部分的做法还是二级缓存处理只不过将 LinkedHashMap+软引用替换成了 LruCache+软引用都是二级缓存,强引用+软引用的结构因为 LruCache 和 LinkedHashMap 都是差不多的处理逻辑没有移除软引用的使用,而是将两者结合了起来根据官网的介绍来看其实软引用效果不大,二级缓存的处理的话 ,虽然能提高一点效果,但是会浪费对内存的消耗所以要不要加个软引用的二级缓存,具体选择就看自己理解和实际应用场景了吧LruCache 我理解是牺牲一小部分效率,换取部分内存

31、我个人也是倾向于只使用 LruCache的实现不用软引用了,也比较简单结合前面举得例子可以理解为,直接取消 NBDL 二级联赛(软引用) 这样能省下好大一笔钱(内存)然后投资联赛其他方面 (处理其他逻辑)并扩展下 NBA 一级联赛(LruCache)的规模 保证复用效率LruCache 的具体用法之前对 LinkedHashMap 有了一定了解了,其实 LruCache 也差不多类似于 removeEldestEntry 方法的回收逻辑,在这个类里面已经处理好了一般我们只需要处理对阀值的控制就行了阀值控制的核心方法是 sizeOf()方法, 该方法的意思是返回每一个 value 对象的大小 s

32、ize默认返回的是 1即当 maxSize(通过构造方法传入)设为 10 的时候就相当于限制缓存池只保留 10 个对象了 和上面 LinkedHashMap 的例子一个意思但是由于图片的大小不一,一般限定所有图片的总大小更加合适 ,那我们就可以对这个 sizeOf方法进行复写Overrideprotected int sizeOf(String key, Bitmap value) return value.getRowBytes() * value.getHeight();这样的话,相当于缓存池里每一个对象的大小都是计算它的字节数 ,则在新建 LruCache 的时候传入一个总 size 值

33、就行了,一般传入应用可用内存的 1/8 大小本篇是讨论对于图片数量的控制问题, 再结合教程(一)中的方法对每一张图片进行相应处理OOM 的情况基本就可以避免了内容比较多,有疑惑的地方或者不足的地方大家可以一起探讨三、Android 开源图片框架分析主要介绍这三个框架,都挺有名的,其他的框架估计也差不多了Android-Universal-Image-LoaderImageLoaderVolley(综合框架,包含图片部分)扯淡时间,可以跳过这段这些开源框架的源码还是挺复杂的,本人技术有限,有部分分析不对的地方或者不足的地方希望大家一起讨论,由于有大量的源代码分析,所以造成内容较多且比较杂乱,重点

34、部分我会用红字或者加粗字体标出来,如果没有耐心全部看完的话可以挑部分重点看,可以跳过的部分我也会有说明,大家可以选择性阅读其实框架的实现和我们教程(一)(二)章的也差不多,只不过在此基础上进行了一些优化,核心部分是几乎没有区别的由于篇幅有限,暂时只介绍第一个框架(其他其实也都差不多),另外两个在后续教程中详细介绍首先介绍 universal-image-loader(以下简称 UIL)是 github 社区上 star 最多的一个项目,可以理解为点赞最多滴, 应该是最有名的一个 国内很多知名软件都用它包括淘宝京东聚划算等等框架其实都差不多,这里详细介绍下使用者最多的一个之后再分析其他框架时就简

35、单说明一些特性了,重复相似部分不再赘述了使用比较简单,这个框架的 github 主页上也有快速使用的步骤基本上就是在 application 类里的 oncreate 方法(整个程序开始时运行一次 )中进行一下简单的基本配置,可以根据需要自行进行设定,懒得设定的话框架也提供了一个默认的配置, 调用一个方法即可基本上是配置一些类似于:缓存类型啊,缓存上限值啊,加载图片的线程池数量 啊等等此外在页面内显示的时候还要设置一个显示配置这个配置不同于基本配置,一个项目里可以根据需要创建多个配置对象使用,这个配置就比较具体了,可以设置是否使用 disk 缓存( 存到 sd 卡里一般),加载图片失败时显示的

36、图片,默认图片,图片的色彩样式等配置好以后,就是简单的使用了,创建一个图片加载对象,然后一行代码搞定显示图片功能 参数一般是入你需要显示的图片 url 和 imageview 对象大部分框架其实都这一个尿性,配置稍微麻烦点,但是使用时一般只需要一行,显示方法一般会提供多个重载方法,支持不同需要由于不是框架使用教程,所以下面结合之前两章的内容着重分析下框架对于单张图片的压缩处理,和多图缓存池的处理单张图片的压缩(业界良心的小技巧: 框架肯定也是基于 android sdk 的, 所以获取图片缩放实例的话,option 的 inSampleSize 参数是肯定要使用的, 我们直接 crtl+h 打

37、开搜索页面, 选择 file search, 然后 file name patterns 选择*.java, 即搜索所有 java 文件, 最后在 containing text 上输入想搜索的内容,这里我们要搜 inSampleSize,搜索结果里随便扫一扫 ,发现BaseImageDecoder 里面有个靠谱的方法如下)mw_shl_code=java,trueprotected Options prepareDecodingOptions(ImageSize imageSize, ImageDecodingInfo decodingInfo) ImageScaleType scaleTy

38、pe = decodingInfo.getImageScaleType();int scale;if (scaleType = ImageScaleType. NONE) scale = ImageSizeUtils. computeMinImageSampleSize(imageSize); else ImageSize targetSize = decodingInfo.getTargetSize();boolean powerOf2 = scaleType = ImageScaleType.IN_SAMPLE_POWER_OF_2 ;scale = ImageSizeUtils. com

39、puteImageSampleSize(imageSize, targetSize, decodingInfo.getViewScaleType(), powerOf2);if (scale 1 Options decodingOptions = decodingInfo.getDecodingOptions();decodingOptions. inSampleSize = scale;return decodingOptions;简单扫一眼,ImageSize,ImageDecodingInfo 神马的明显是自定义的一个类,不要管, 我们先挑重点部分看Options decodingOpt

40、ions = decodingInfo.getDecodingOptions();decodingOptions.inSampleSize= scale;方法最后两行可以看出来 ImageDecodingInfo 类里面保存了一个 option 对象通过一个方法对其中的 inSampleSize 进行了设置ImageScaleType.NONE 什么意思 ,扫了眼注释,是图片无压缩 那我们看 else 里面的需要压缩的 computeImageSampleSize 方法方法是具体如何处理的呢 我们再继续跟踪 computeImageSampleSize 方法 (业界良心小技巧:按着 ctrl

41、不松左键点击方法或者变量或者类,就可以自动跳转到对应的地方了)方法的代码如下/* Computes sample size for downscaling image size ( srcSize ) to view size (targetSize ). This sample* size is used during* linkplain BitmapFactory#decodeStream(java.io.InputStream, android.graphics.Rect, android.graphics.BitmapFactory.Options)* decoding image

42、to bitmap.* * Examples: * * * srcSize(100x100), targetSize(10x10), powerOf2Scale = true - sampleSize = 8* srcSize(100x100), targetSize(10x10), powerOf2Scale = false - sampleSize = 10* srcSize(100x100), targetSize(20x40), viewScaleType = FIT_INSIDE - sampleSize = 5* srcSize(100x100), targetSize(20x40

43、), viewScaleType = CROP - sampleSize = 2* * * * The sample size is the number of pixels in either dimension that correspond to a single pixel in the decoded* bitmap. For example, inSampleSize = 4 returns an image that is 1/4 the width/height of the original, and 1/16* the number of pixels. Any value

44、 true - if sample size be a power of 2 (1, 2, 4, 8, .)* return Computed sample size*/public static int computeImageSampleSize(ImageSize srcSize, ImageSize targetSize, ViewScaleType viewScaleType,boolean powerOf2Scale) int srcWidth = srcSize.getWidth();int srcHeight = srcSize.getHeight();int targetWi

45、dth = targetSize .getWidth();int targetHeight = targetSize .getHeight();int scale = 1;int widthScale = srcWidth / targetWidth;int heightScale = srcHeight / targetHeight;switch (viewScaleType) case FIT_INSIDE:if (powerOf2Scale) while (srcWidth / 2 = targetWidth | srcHeight / 2 = targetHeight) / |srcW

46、idth /= 2;srcHeight /= 2;scale *= 2; else scale = Math. max(widthScale, heightScale); / maxbreak;case CROP:if (powerOf2Scale) while (srcWidth / 2 = targetWidth srcHeight /= 2;scale *= 2; else scale = Math. min(widthScale, heightScale); / minbreak;if (scale = 200 | 600/2 = 200 都满足, 源宽高变成一半 500 400,缩放

47、值翻倍,变成 2第二次循环,500/2 = 200 | 300/2 = 200 满足其中一个, 源宽高变成一半 250 200,缩放值翻倍,变成 4第三次循环,250/2 = 200 | 150/2 = 200 都不满足,结束循环,最后缩放值为 4以缩放比例 4 计算,获得的缩放图片实例的宽高即为 250 150CROP 效果时的处理第一次循环,1000/2 = 200 import android.graphics.Bitmap;import com.nostra13.universalimageloader.cache.memory.MemoryCache;import java.util

48、.Collection;import java.util.HashSet;import java.util.LinkedHashMap;import java.util.Map;/* A cache that holds strong references to a limited number of Bitmaps. Each time a Bitmap is accessed, it is moved to* the head of a queue. When a Bitmap is added to a full cache, the Bitmap at the end of that queue is evicted and may* become eligible for garbage collection.* * NOTE: This cache uses only strong references for stored Bitmaps.* author Sergey Tarasevich (nostra13atgmaildotcom)* since 1.8.1*/public class LruMemoryCache implements Memory

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 建筑环境 > 建筑资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报