Android 包体积优化建议-资源篇

这是 Android 官方文档给出的一些减少包体积的建议,最近正好在看这方面内容,顺手记录、分享一下。本文主要是针对 Android 的资源(Resource) 相关优化建议。

1 移除无用资源

使用 lint 静态代码分析工具 查找出未使用的 res 资源。

注意 assertlib 下的未使用资源无法检测出来,其中 assert/ 资源引用采用的是反射方法。 除了检测工具外,Gradle 还支持在打包编译的时候自动移除无用资源,使用 shrinkResources

groovy 复制代码
android {
    // Other settings
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

这里 minifyEnabled 需要一起打开,即代码压缩。这样编译的时候会先用 R8 进行无用代码移除,然后 gradle 插件进行无用资源的移除。详细使用参考:Shrink, obfuscate, and optimize your app

除此之外,还可以使用 resConfig 配置针对指定的 flavor 来打包指定的资源。比如外发包的图片和第一方的包的资源不一样,配置在不同的文件夹下,打包的时候就可以只打包指定的文件夹资源,这样也能减少一定的体积。

2 减少依赖库大小

开发的时候,在选择第三方工具库时,需要关注一下该库的大小。比如 Android 图片加载库 GlidePicassoFresco 的选择,将依赖库的体积大小作为选用的衡量标准之一。

另外,如果只是使用某个工具库的其中一个(小)功能,是否可以考虑将其下载下来自行修改,适当移除不需要的功能代码,从而减少依赖库的体积。

3 原生动画图片支持

使用 ImageDecoder 原生 API 支持带动画的 GIF 和 WebP 的图片文件格式,从而删除第三方库减少包体积。

要求 Android 11 以上才支持

4 支持特定分辨率

从 Android 4.4 开始,支持 ldpi, mdpi, tvdpi, hdpi, xhdpi, xxhdpixxxhdpi 这么多的分辨率(屏幕密度,density),但是没有必要给每个分辨率都制作对应的图片资源。

也许你的用户只有 0.1% 的人需要 ldpi ...

这个时候,其实我们只需要一种分辨率的文件夹,比如 drawable-nodpi/,对于其他的,系统会自动适配(放大缩小)

官方推荐至少有一种分辨率 xxhdpi

5 使用 drawable 或代码渲染图片

有些单色背景图片其实不需要静态的图片文件,使用 Drawable 对象(xml 里的 )可以在运行的时候绘制出来,从而节省出静态图片文件的大小。

对应的,使用代码来生成某些简单的效果图(render from code),比如页面背景设置为纯色。

相比使用图片文件,可以减小一定的包体积大小。

6 复用资源

某些情况下,两张图片可能除了角度或者颜色不一样,其他都是一样的,这个时候,我们就不推荐使用2张图片,可以通过代码来上色或者旋转。

图片的纯上色(改变颜色),大于 Android 5.0(API 21) 的系统可以使用 android:tinttintMode ,小于 Android 5.0 的版本使用 ColorFilter 来完成。

改变图片的旋转角度,比如上箭头改为下箭头这种,使用下面这样即可:

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/ic_thumb_up"
    android:pivotX="50%"
    android:pivotY="50%"
    android:fromDegrees="180" />

7 压缩图片资源文件

官方内置的工具 aapt ,在编译的时候,会自动对 res/drawable/ (其他目录无效,比如 asset/ )里面的图片进行无损压缩(lossless compression),如果不需要,可以手动关闭:

groovy 复制代码
buildTypes.all { isCrunchPngs = false }

需要注意的是,isCrunchPngs 在 release 默认打开(这会增加编译时间),debug 下默认关闭。

选用第三方工具进行不同格式图片压缩:

8 使用 WebP 文件格式

Android 3.2(API 13) 之后开始支持 WebP 图片格式。

WebP 相比 JPEG 和 PNG 有更好的压缩效率(即压缩的体积更多,损失越小),可以直接在 Android Studio 里面将 BMP, JPG, PNG 或者静态 GIF 图片转换为 WebP 格式。

JPEG 为有损压缩(lossy compression) PNG 为无损数据压缩,主要体现在透明度上的变化。(lossless data compression,a raster-graphics file format)

9 使用矢量图形(vector graphics)

矢量图形是一种与分辨率无关的图片,100字节大小的文件可以描述出充满整个屏幕的高清图片。

矢量图形在代码里用 VectorDrawable 表示。

但是有一定的性能问题。矢量图形本质上就是一系列 xml 数据,Android 系统根据矢量图形的"描述"调用 cpu\gpu 去绘制出来一张图:比如x坐标以上涂满红色,y坐标以下涂满绿色,哪里哪里填上灰色...

适合用于小面积的图标(icon)绘制,不适合大面积的图像绘制,有一定的性能消耗。

例子:

ini 复制代码
<!-- res/drawable/battery_charging.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="24dp"
    android:width="24dp"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">

   <group
         android:name="rotationGroup"
         android:pivotX="10.0"
         android:pivotY="10.0"
         android:rotation="15.0" >

      <path
        android:name="vect"
        android:fillColor="#FF000000"
        android:pathData="M15.67,4H14V2h-4v2H8.33C7.6,4 7,4.6 7,5.33V9h4.93L13,7v2h4V5.33C17,4.6 16.4,4 15.67,4z"
        android:fillAlpha=".3"/>

      <path
        android:name="draw"
        android:fillColor="#FF000000"
        android:pathData="M13,12.5h2L11,20v-5.5H9L11.93,9H7v11.67C7,21.4 7.6,22 8.33,22h7.33c0.74,0 1.34,-0.6 1.34,-1.33V9h-4v3.5z"/>
   </group>
</vector>

渲染生成:

还有动画效果也可以使用 vector graphics 来实现,参考 AnimatedVectorDrawableCompat

(对比使用逐帧动画,需要放入大量的单帧图片组合一个动画,极大增加了apk包大小!)

参考

Reduce your app size

相关推荐
dream_ready44 分钟前
linux安装nginx+前端部署vue项目(实际测试react项目也可以)
前端·javascript·vue.js·nginx·react·html5
编写美好前程1 小时前
ruoyi-vue若依前端是如何防止接口重复请求
前端·javascript·vue.js
flytam1 小时前
ES5 在 Web 上的现状
前端·javascript
喵喵酱仔__1 小时前
阻止冒泡事件
前端·javascript·vue.js
GISer_Jing1 小时前
前端面试CSS常见题目
前端·css·面试
八了个戒1 小时前
【TypeScript入坑】什么是TypeScript?
开发语言·前端·javascript·面试·typescript
不悔哥1 小时前
vue 案例使用
前端·javascript·vue.js
anyup_前端梦工厂2 小时前
Vuex 入门与实战
前端·javascript·vue.js
你挚爱的强哥2 小时前
【sgCreateCallAPIFunctionParam】自定义小工具:敏捷开发→调用接口方法参数生成工具
前端·javascript·vue.js
米老鼠的摩托车日记3 小时前
【vue element-ui】关于删除按钮的提示框,可一键复制
前端·javascript·vue.js