geekband android #5 第十三周分享(Btimap优化)

来源:互联网 发布:java list泛型 遍历 编辑:程序博客网 时间:2024/05/19 03:18

一.Bitmap优化

1.Bitmap decode

jpg:有压缩特别是当色彩丰富时

png:无损压缩

webp:google近年开发的无损的情况下仍保证内存占用不会过大


Re-using Bitmaps 每产生一个bitmap会分配一个内存    创建→回收→创建→回收→......

bitmap占用大量内存,所以当bitmap使用较多之后会引起GC,频繁的GC导致内存抖动的话影响产品性能、用户体验。


目前一般采用为图片分配一个对象池(申请一块内存空间,常为一个经验值)。虚拟机给一张图片对象分配内存,当获取第二张图片时覆盖第一张的内存,

第三张图片以此类推。Coding如下:



2.Pre-scaling Bitmap 

当我们需求的图片大小比原图小时,可以采用保证质量的压缩。


inSampleSize = 1  2  4  分别对应  fullsize  1/2size  1/4size 

在这之前,我们需要获取原图片的宽高信息

在不加载图片的情况下:options.inJustDecodeBounds=true

inTargetDensity/inDensity的实现。

调Bitmap的decodeResourse方法,传入res,resID,option

判断宽高然后计算inSampleSize(1 / 2的n次方)

while循环的计算,取到inSampleSize返回值赋给option然后调用一次decodeResourse将option传过去。




3.Smaller Pixel Format :减小bitmap每一个像素占用内存大小而非压缩宽高。

四种像素格式:

ARGB_8888:图位数较高,储存的信息数较多,图像很逼真。占3个字节。

RGB_565:需要用大图,但不需支持透明度时。占2个字节。

ARGB_4444:需要用大图,也需要用透明度时。占2个字节。

ALPHA_8:只有透明度。一个像素占1个字节。

        RGB_565和ARGB_4444,占用内存小,且在非icon下与ARGB差别不大。

        只有透明度的ALPHA_8 + color tint 可以达到ARGB_8888能达到的要求,并且占用内存远小于ARGB_8888。但会耗费CPU进行计算。

指定你想要的像素格式(decode耗时操作通常不放在UI线程中进行)



4.Smaller PNG files



二.其他优化

1.Method Profiling 可以看到每个线程/方法占用时间

        使用:AS中advice monitor → 选中进程(左侧)→ start Method Profiling → stop → 显示统计


2.Lint Tool 对Java 代码做静态检查:程序可用性、代码安全性、代码可用性、可优化性。

使用方式:Release Builds

                    Command Line 一般配合CI使用

                    Manually 常用,在AS中手动执行一次Lint

                                     AS → Analyze → Inspect → code → whole → project → ok → 显示在inspection 

                                    关于配置:Editor → Inspections → 检索performance(由于多数只关注性能)


3.Android-specific Containtors

            Primitive sizes                                                                       Object Sizes

boolean 8bits                                                            boolean    java.long.Boolean

int 32bits                                                                    int  java.long.Integer

float 32bits                                                                 float  java.long.Float

long 64bits

                                  (Autoboxing)

integer        value           =          0        (Primitive int)  

              (integer object)

自动装箱耗费内存给程序带来负担


4.优化HashMap

当元素小,数量很多,且HashMap发生多层嵌套的时候。


5.枚举Enum

由于无法控制用户是否会输入一些非法字节,当开发者不想加入判断语句时,可以采用枚举将工作抛给编译器

android提供的工具:



三.实践:图片加载库

五个方面可以优化:高效加载大图,在非UI线程处理,缓存,内存管理,显示。

(加载原始图片大小之后改变显示大小并不会减少内存使用)

1.高效加载大图(以下代码未加括号,只起示意方法作用)

BitmapFactory.Options options = new BitmapFactory.Options( );

//获取原始属性宽高

options.inJustDecodeBounds = ture 

//保存在options.outwidth和options.outHeight 这两个属性中

options.inSampleSize = 4 

Bitmap bitmap = BitmapFactory.decodeResource(getResources() , R.drawable.big , options );

//创建一个方法:

private int calculateInSampleSize(BitmapFactory.Option options , int requestWidth , int requestHeight )

int originWidth = option.outWidth

int originHeight = option.outHeight

int inSampleSize = 1 

//加入一个判断

if ( originWidth <requestWidth &&originHeight <  requestHeight )

while (originHeight/inSampleSize  > requestHeight && originWidth/inSampleSize  > requestWidth)

    inSampleSize  *= 2  


2.优化解码过程,将decode放入非UI线程。Device Monitor

(主要在十三章第三节的第二个视频,异步解码图片,略微复杂,暂时省略)


3.缓存:

磁盘缓存 :disc LruCache

内存缓存:

LruCache <String , 资源名> mBitmapLruCache 

....

....

mBitmapLruCache.put( "resId:" + resId , bitmap)


private set <WeakReference<Bitmap>> mReusableBitmapSet = Collections.synchronizedSet(new HashSet<WeakReference<Bitmap>>());

然后在entrykemoved方法中

    mResuableBitmapSet.add( new WeakReference <Bitmap>(oldValue));

然后在do Inbackground这个方法中回调decodeResource方法

    这是需要创建一个addInBitmapOptions(mOptions)在do Inbackground中

        而又需要创建一个findCandidate方法在addInBitmapOptions(mOptions)中

        并且在里面实现candidateMeets方法,创建getPixelSize方法,判断图片类型返回字节数。


0 0
原创粉丝点击