APP的优化是任重而道远的过程,必须在意每一个环节,否者当你想要优化的时候,发现到处都是坑,已经不知道填补哪里了,所以我们必须一点一滴的做起。
Bitmap
Bitmap的内存管理优化
大量Bitmap的创建和垃圾回收,会产生内存抖动,引发卡顿。一次性加载超大的图片会导致OOM,所以我们要避免或者合理的使用循环缩放,压缩,缩放的目的主要是合理的使用(避免大图加载OOM,因为手机实际是用不到那么大的图片的)。或者使用一些比较好的第三方工具如Glide。(不要怀疑bitmap的优化就是这么一句。)
Bitmap相关方法总结
public void recycle() // 回收位图占用的内存空间,把位图标记为Dead
public final boolean isRecycled() //判断位图内存是否已释放
public final int getWidth() //获取位图的宽度
public final int getHeight() //获取位图的高度
public final boolean isMutable() //图片是否可修改
public int getScaledWidth(Canvas canvas) //获取指定密度转换后的图像的宽度
public int getScaledHeight(Canvas canvas) //获取指定密度转换后的图像的高度
public boolean compress(CompressFormat format, int quality, OutputStreamstream) //按指定的图片格式以及画质,将图片转换为输出流
public static Bitmap createBitmap(Bitmap src) //以 src 为原图生成不可变得新图像
public static Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter) //以 src 为原图,创建新的图像,指定新图像的高宽以及是否可变。
public static Bitmap createBitmap(int width, int height, Config config) //创建指定格式、大小的位图
public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height) //以 source 为原图,创建新的图片,指定起始坐标以及新图像的高宽。
BitmapFactory工厂类
Option 参数类
public boolean inJustDecodeBounds
//如果设置为 true ,不获取图片,不分配内存,但会返回图片的高度宽度信息。如果将这个值置为 true ,那么在解码的时候将不会返回 bitmap ,只会返回这个 bitmap 的尺寸。这个属性的目的是,如果你只想知道一个 bitmap 的尺寸,但又不想将其加载到内存时。这是一个非常有用的属性。
public int inSampleSize
//图片缩放的倍数, 这个值是一个 int ,当它小于1的时候,将会被当做1处理,如果大于1,那么就会按照比例 (1 / inSampleSize) 缩小 bitmap 的宽和高、降低分辨率,大于1时这个值将会被处置为2的倍数。例如, width=100,height=100,inSampleSize=2 ,那么就会将 bitmap 处理为, width=50,height=50 ,宽高降为1 / 2,像素数降为1 / 4。
public int outWidth //获取图片的宽度值
public int outHeight //获取图片的高度值 ,表示这个 Bitmap 的宽和高,一般和
inJustDecodeBounds 一起使用来获得 Bitmap 的宽高,但是不加载到内存。
public int inDensity //用于位图的像素压缩比
public int inTargetDensity //用于目标位图的像素压缩比(要生成的位图)
public byte[] inTempStorage //创建临时文件,将图片存储
public boolean inScaled //设置为 true 时进行图片压缩,从 inDensity 到inTargetDensity
public boolean inDither //如果为 true ,解码器尝试抖动解码
public Bitmap.Config inPreferredConfig //设置解码器,这个值是设置色彩模式,默认值是 ARGB_8888 ,在这个模式下,一个像素点占用4bytes空间,一般对透明度不做要求的话,一般采用 RGB_565 模式,这个模式下一个像素点占用2bytes。
public String outMimeType //设置解码图像
public boolean inPurgeable //当存储 Pixel 的内存空间在系统内存不足时是否可以被回收
public boolean inInputShareable // inPurgeable 为 true 情况下才生效,是否可以共享一个 InputStream
public boolean inPreferQualityOverSpeed //为 true 则优先保证 Bitmap 质量其次是解码速度
public boolean inMutable //配置 Bitmap 是否可以更改,比如:在 Bitmap 上隔几个像素加一条线段
public int inScreenDensity//当前屏幕的像素密度
工厂方法
public static Bitmap decodeFile(String pathName, Options opts) //从文件读取图片
public static Bitmap decodeFile(String pathName)
public static Bitmap decodeStream(InputStream is) //从输入流读取图片
public static Bitmap decodeStream(InputStream is, Rect outPadding, Optionsopts)
public static Bitmap decodeResource(Resources res, int id) //从资源文件读取图片
public static Bitmap decodeResource(Resources res, int id, Options opts)
public static Bitmap decodeByteArray(byte[] data, int offset, int length) //从数组读取图片
public static Bitmap decodeByteArray(byte[] data, int offset, int length,Options opts)
public static Bitmap decodeFileDescriptor(FileDescriptor fd) //从文件读取文件 与decodeFile 不同的是这个直接调用JNI函数进行读取 效率比较高
public static Bitmap decodeFileDescriptor(FileDescriptor fd, Rect outPadding,Options opts)
单个像素的字节大小
单个像素的字节大小由Bitmap的一个可配置的参数Config来决定。
Bitmap中,存在一个枚举类Config,定义了Android中支持的Bitmap配置:
Bitmap加载方式
Bitmap 的加载方式有 Resource 资源加载、本地(SDcard)加载、网络加载等加载方式。(详细不细说)
Bitmap的内存回收
使用Bitmap.recycle()方法进行Bitmap的内存回收。
drawable图片加载放置
图片放在某个特定drawable中,比如drawable-hdpi,如果设备的屏幕密度高于当前drawable目录所代表的密度,则图片会被放大,否则会被缩小放大或缩小比例 = 设备屏幕密度 / drawable目录所代表的屏幕密度。
Bitmap长图加载
思路,通过获取需要加载的部分高宽:使用decodeRegion区域加载,使用BigmapRegionDecoder流方式加载,对图像进行部分加载。