【Android性能优化面试题】如何对apk进行瘦身

如何对apk进行瘦身

这道题想考察什么?

  1. 是否了解如何对apk进行瘦身的真实场景使用,是否熟悉如何对apk进行瘦身做处理所引发的场景?

考察的知识点

  1. 如何对apk进行瘦身在项目中使用与基本知识

考生应该如何回答

APK的大小对于app载入速度、占用内存大小以及耗电量有着很大的影响。一般而言,用户并不太喜欢下载APK体积太大的app。尤其是对于流量、手机内存有限的用户来讲,太大的APK往往会让他们望而却步,所以需要做APK瘦身。

想要对APK进行瘦身,必须得先了解APK的组成结构,只有了解APK由哪些部分组成,你才能有所针对性的进行APK瘦身。
APK主要由以下几部分组成:

  • META-INF/ :包含了签名文件CERT.SFCERT.RSA,以及 manifest 文件MANIFEST.MF
  • assets/ : 存放资源文件,这些资源不会被编译成二进制。
  • lib/ :包含了一些引用的第三方库。
  • resources.arsc :包含res/values/中所有资源,例如strings,styles,以及其他未被包含在resources.arsc中的资源路径信息,例如layout 文件、图片等。
  • res/ :包含res中没有被存放到resources.arsc的资源。
  • classes.dex :经过dx编译能被android虚拟机理解的Java源码文件。
  • AndroidManifest.xml :这个不用解释

通过android studio --> build --> Analyze APK 来查看一下上述各个部分文件大小情况:

如下图中:占用空间的主要是代码、res 和 lib ,因为我的assets中没有放文件,所以看起来并没有占用什么空间,其实assets中文件放的多,一样会占用很大空间。所以APK瘦身时,主要就从代码reslibassets这几个方面重点考虑:

image.png

减少资源文件数量和大小

必须明白,APK瘦身的一个很简单的办法就是减少资源文件的数量和大小

去除无用资源

使用lint工具来检测res/中是否有没有使用到的资源

然而对于一些第三方库来说,使用lint可能无法检测到,我们可以使用shrinkResources来删除库文件中无用的资源,配合proguard压缩代码使用

android {
    // Other settings

    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

移除未使用的备用资源。例如对于一些第三库来说,因为国际化的问题,它们可能会支持了几十种语言,但我们的应用可能只需要支持中文就行了,这时候我们就可以使用resConfigresConfigs来解决。
下面这段代码展示了如何将语言资源限定为仅支持中文:

android {
    defaultConfig {
        ...
        resConfigs "zh"
    }
}

使用最小化资源的库

开发项目的时候,经常会用到许多第三方库,但第三方库往往可能会很大,那怎么来进行压缩呢?

  • 使用ProGuard压缩代码,然后配合shrinkResources使用,方法见上面shrinkResources的使用。

  • 然而ProGuard只能压缩库本身的一些没有用到的代码,但库内部本身可能仍依赖了其他的第三方库,对于这些库ProGuard却无法进行有效去除。
    很多第三方库会提供多种版本,例如完整版、精简版、针对某个功能的特殊版,你只需要选择能包含你需要功能的体积最小版本库。当然如果你能获得源码,自己提炼出你所需要的功能就更好了。

只支持特定屏幕密度

Android支持多种屏幕密度设备,Android 4.4以上版本支持包括:ldpi, mdpi, tvdpi, hdpi, xhdpi, xxhdpi and xxxhdpi。尽管Android支持了这么多屏幕密度,但你并不需要全部支持,你可以根据你的需求来选择支持。

使用drawable 对象

对于一些简单的images可以不使用图片,使用Drawable XML来进行绘制。

复用资源

对于相似的一些Image可以复用同一张图片。

  • 形状一样,但颜色、阴影有区别的Image;在 Android 5.0 (API level 21)以及以上版本,可以使用android:tint, tintMode等属性去调整,在Android 5.0以下可以使用ColorFilter来调整。

  • 形状颜色一样,但角度不一样的Image;可以使用rotate等来调整角度达到复用效果。例如:

    <?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" />
    

代码渲染

你也可以通过代码渲染来代替使用图片,例如使用自定义View绘制。图片减少了,APK自然瘦身了。

紧缩PNG文件

AAPT工具会在构建期间自动对res/drawable/文件夹下的PNG图片资源做无损压缩。例如,一张true-color的PNG图片,如果它实际需要的颜色不大于256种,那么就有可能会被转换成一张8位的调色板图片(PNG8)。转换之后的图片质量未减却只占用更小的内存。

压缩PNG和JPG

你可以使用pngcrush, pngquantzopflipng来压缩PNG图片。
使用packJPGguetzli 来压缩JPG图片。

使用WebP

你可以使用 WebP 来代替JPG和PNG图片。WebP 保留了JPG和PNG优点的同时,能提供更好的压缩,达到更小的体积。

注意事项:启动图标最好不要用WebP,因为谷歌商店只接受启动图片格式为PNG的APK。

使用矢量图形

你可以使用矢量图形来绘制分辨率无关图标及其他可伸缩媒体文件。整个屏幕那么大的清晰图片,如果使用矢量图可能只需要100-byte大小。
然而使用矢量图形会让系统花更多的时间来进行绘制,所以最好只在比较小的images上使用矢量图。

将矢量图形用于动画图像

不要使用AnimationDrawable来创建帧动画,否则每一帧就用一张图片会占用大量的空间。这个时候你应该使用AnimatedVectorDrawableCompat

删除不必要的生成代码

要确保能够了解自动生成的代码用途,例如有很多的protocol buffer tools会自动生成大量你可能用不到的代码。

避免使用枚举

一个单独的枚举可以将apk增加1.0 到1.4 KB大小,对于复杂的系统或者共享库来说,累积下来可能会增加相当大的APK体积。
如果可能的话,可以考虑使用@IntDef注解和ProGuard来剥离枚举并将它们转换为整数。这种类型转换保留了枚举的类型安全优势。

减少本地二进制文件的大小

如果你的APP使用native code 和 Android NDK,那么可以通过两种方法优化代码,达到减小APK大小的效果。

  • 删除Debug符号
    使用Android NDK中提供的arm-eabi-strip工具来移除Native库中不必要的Debug符号。

  • 避免提取本地库
    在 Android 6.0 之前, so 文件会压缩到 apk 中,系统在安装应用的时候,会把 so文件解压到 data 分区,这样同一个 so 文件会有两份存在,一个在 apk 中一个在 data 区中, 导致多占用了一倍空间。 从 Android 6.0 开始,你可以在 AndroidManifest.xml 中使用一个新的属性:

    如下:该属性告诉系统,不要把 so 文件从 apk 中解压出来了,并且修改 System.loadLibrary 调用直接从 apk 中打开 so 文件:

    <application
     android:extractNativeLibs=”false”
     ...
    >
    

维护多个精简版APK

你的APP中可能会包含许多用户根本不会使用的内容,例如区域和语言信息。你可以根据屏幕尺寸或GPU纹理支持等因素针对性提供不同版本的APK。当用户下载APK的时候,会根据手机的特性和设置有针对性的下载特定版本APK,这样的话用户就不会下载到他根本不需要的内容

android {
  ...
  splits {
    //根据屏幕像素密度来创建多个APK
    density {
      enable true
      //根据屏幕密度创建两个版本APK,"mdpi", "hdpi"
      reset()
      include "mdpi", "hdpi"
    }
    //根据手机cpu指令集分类创建多个APK
    abi {
      enable true
      //创建 "x86", "x86_64"两个版本APK
      reset()
      include "x86", "x86_64"
    }
  }
}

我们来编译一下APK看下结果:

image.png

分析上图中可以看到生成了6个APK,为什么是6个?
答:

首先屏幕密度有三个版本(mdpi, x86_64,gralde还会生成一个包含所有屏幕密度资源的默认版本),ABI指令集有两个版本(gralde默认编译不会添加包含所有ABI指令集版本的APK,如果你想添加,需要在abi代码块中加上universalApk true),它们两两组合为6种。每个APK里只会包含它对应的资源,例如app-hdpiX86-debug.apk中只会存在屏幕密度为hdpi的资源以及X86的库文件。
如果你的手机cpu指令集是x86,屏幕密度为hdpi,那么你会下载到app-hdpiX86-debug.apk


最后

有需要面试题的朋友可以关注一下哇哇,以上都可以分享!!!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,490评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,581评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,830评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,957评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,974评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,754评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,464评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,847评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,995评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,137评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,819评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,482评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,023评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,149评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,409评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,086评论 2 355

推荐阅读更多精彩内容