阿里Android开发手册读后感 下篇

阅读阿里安卓开发手册系列最后一篇,以下是一些让我印象深刻的点,顺带记录自己简单的思考

【强制】使用完毕的图片,应该及时回收,释放宝贵的内存。

我的思考:
及时回收的含义是说,对于Bitmap对象用完后要在Activity回调方法里置空。

【推荐】应根据实际展示需要,压缩图片,而不是直接显示原图。
【推荐】使用 ARGB_565 代替 ARGB_888,在不怎么降低视觉效果的前提下,减少内存占用

说明:

android.graphics.Bitmap.Config 类中关于图片颜色的存储方式定义:

  1. ALPHA_8 代表 8 位 Alpha 位图;
  2. ARGB_4444 代表 16 位 ARGB 位图;
  3. ARGB_8888 代表 32 位 ARGB 位图;
  4. RGB_565 代表 8 位 RGB 位图。

位图位数越高,存储的颜色信息越多,图像也就越逼真。大多数场景使用的是 ARGB_8888 和 RGB_565,RGB_565 能够在保证图片质量的情况下大大减少内存的开销,是解决 oom 的一种方法。

但是一定要注意 RGB_565 是没有透明度的,如果图片本身需要保留透明度,那么就不能使用 RGB_565。

我的思考:
压缩图片有两种方式:1.采样压缩 2.质量压缩

采样压缩模版代码:

fun sampleBitmapFromResource(res: Resources, resId: Int, reqWidth: Int, reqHeight: Int): Bitmap {
    val options = BitmapFactory.Options()
    options.inJustDecodeBounds = true
    BitmapFactory.decodeResource(res, resId, options)
    options.inJustDecodeBounds = false
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight)
    return BitmapFactory.decodeResource(res, resId, options)
}

fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int {
    var outWidth = options.outWidth
    var outHeight = options.outHeight
    var sampleSize = 1
    while (outWidth > reqWidth || outHeight > reqHeight) {
        outWidth = outWidth / 2
        outHeight = outHeight / 2
        sampleSize = sampleSize * 2
    }
    return sampleSize
}

质量压缩就是把没有透明度的位图从ARGB_8888转成RGB_565,让每个像素占用的内容从4byte降到1byte。

Drawable转BitmapKotlin代码:

fun drawableToBitmap(drawable: Drawable): Bitmap {
    return when (drawable) {
        is BitmapDrawable -> drawable.bitmap
        else -> {
            val config = if (drawable.opacity != PixelFormat.OPAQUE)
                Bitmap.Config.ARGB_8888
            else
                Bitmap.Config.RGB_565

            val intrinsicWidth = drawable.intrinsicWidth
            val intrinsicHeight = drawable.intrinsicHeight
            val bitmap = Bitmap.createBitmap(Math.max(intrinsicWidth, 2), Math.max(intrinsicHeight, 2), config)
            val canvas = Canvas(bitmap)
            drawable.setBounds(0, 0, canvas.width, canvas.height)
            drawable.draw(canvas)
            return bitmap
        }
    }
}

【推荐】使用inBitmap重复利用内存空间,避免重复开辟新内存

【强制】META-INF 目录中不能包含如.apk,.odex,.so 等敏感文件,该文件夹没有经过签名,容易被恶意替换

【推荐】在有强依赖 onAnimationEnd 回调的交互时,如动画播放完毕才能操作页面,onAnimationEnd 可能会因各种异常没被回调,建 议加上超时保护或通过postDelay替代onAnimationEnd