zoukankan      html  css  js  c++  java
  • 让你的APK瘦成一道闪电

    APK瘦身是长久以来的难题,我们需要通过一些工具和技巧才能让它瘦下去,下面我来分享一下我在apk瘦身方面的经验。

    一、apk中有哪些东西

    1.代码

    2.lib

    3.so本地库

    4.资源文件(图片,音频,字体等)

    二、针对性解决问题

    1.代码

    我们代码的优化可以通过混淆来删除没有用到的代码:

    buildTypes {
            debug {
               
            }
            release {
                minifyEnabled true // 是否混淆
                shrinkResources true // 是否去除无效的资源文件
                // 混淆的配置文件
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }

    详细请参考:http://www.cnblogs.com/tianzhijiexian/p/4457763.html

    2.lib

    尽量不用太复杂的lib,轻量级lib是首选。如果你的应用没用到兼容库,可以考虑去掉support包。

    3.so本地库

    一个硬件设备对应一个架构(mips、arm或者x86),只保留与设备架构相关的库文件夹(主流的架构都是arm的,mips属于小众,默认也是支持arm的so的,但x86的不支持)

    4.资源文件

    通过Lint工具扫描代码中没有使用到的静态资源。请参考:

    在Android Stuido中使用Lint

    需要注意的是:Lint 会分析资源文件(比如 /res 文件夹下面的文件) ,但是会跳过 assets 文件 ( /assets 文件夹下面的文件)。事实上assets 文件是可以通过它们的文件名直接访问的,而不需要通过Java引用或者XML引用。因此,Lint 也不能判定某个 asset 文件在项目中是否有用。这全取决于开发者对这个文件夹的维护了。如果你没有使用某个asset 文件,那么你就可以直接清除这个文件。

    5.用一张图片来实现button.selector的多种状态

    解决思路是:用通用的遮罩来建设重复的图片,详情参考:

    用一张图片实现按钮按下和普通效果的样式

    如果是5.0以上的版本:

    通常按钮的正反旋图片我们都是通过提供一张按钮正常图片和一张按钮反选图片,然后通过selector实现,两张图片除了alpha值不一样外其它的内容都是重复的,在Android 5.0及以上的版本可以通过tintcolor实现只提供一张按钮的图片,在程序中实现按钮反选效果,前提是图片的内容一样,只是正反选按钮的颜色不一样。

    6.复用现有的图片,多用shape和layer-list

    shape和layer-list一个可以画出很多常规的图像,另一个可以将现有的图像进行组合。通过这两个东西可以让我们最大限度的复用现有的图片。尽可能的重用已有的图片资源。

    对于下面的图片:

    我们可以只要求设计师提供铅笔的icon,后面用shape画一下背景就好,而不是要全部的图片。

    对于对称的图片,只需要提供一张,另外一张图片可以通过代码旋转的方式实现,需要用到的就是animation的一个小技巧。下面分享一下使用的步骤:

    我建立一个rotate_drawable.xml文件:

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

    然后,在button设置background:

    <ImageButton
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:background="@drawable/rotate_drawable"/>

    7.优化现有的图片

    • jpeg还是png,根据需要做选择,在某些时候jpeg可以减少图片的体积。
    • 对于9.png的图片,可拉伸区域尽量切小,另外可以通过使用9.png拉伸达到大图效果的时候尽量不要使用整张大图。
    • 有选择性的提供hdpi,xhdpi,xxhdpi的图片资源。建议优先提供xhdpi的图片,对于mdpi,ldpi与xxxhdpi根据需要提供有差异的部分即可。

    8.压缩现有的图片

    图片资源的优化原则是:在不降低图片效果、保证APK显示效果的前提下缩小图片文件的大小。

    8.1 使用tinypng优化大部分图片资源:

    使用tinypng优化Android的资源图片

    tinypng的缺点是在压缩某些带有过渡效果(带alpha值)的图片时,图片会失真,这种图片可以将png图片转换为下面介绍的webP格式,可以在保证图片质量的前提下大幅缩小图片的大小。

    8.2 把现有图片转换为webP

    其他图片和webP之间相互转换

    10.使用VectorDrawable和SVG图片来替换原有图片

    用svg替换原来图片可是一个大杀,能立刻将图片减少,而且不用考虑分辨率适配的问题。那么将svg图片导入工程呢?答:需要配合vectorDrawable。

    在android5.0(API Level 21)中,我们可以使用矢量图:vector drawable,vector drawable的特点是它不会因为图像的缩放而失真。在安卓开发中也就意味着你不需要为不同分辨率的设备定义不同大小的图片资源,只需一个vector drawable就够了。

    <!-- res/drawable/vectordrawable.xml -->
    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:height="64dp"
        android:width="64dp"
        android:viewportHeight="600"
        android:viewportWidth="600">
        <group
            android:name="rotationGroup"
            android:pivotX="300.0"
            android:pivotY="300.0"
            android:rotation="45.0" >
            <path
                android:name="v"
                android:fillColor="#000000"
                android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
        </group>
    </vector>

    如果想深入了解请参考:

    http://jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0123/2346.html

    http://jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0201/2396.html

    http://jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0301/2514.html

    http://jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0301/2515.html

    http://jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0306/2553.html

    在低版本中可以使用开源的第三方库来实现:

    https://github.com/wnafee/vector-compat

    https://github.com/telly/MrVector

    9.资源文件最少化配置

    Android 开发经常会依赖各种外部开源代码库,比如Android Support Library, Google Play Services, Facebook SDK 等等。但是这些库里面并不是所有的资源文件你都会用到。比如, Google Play Services 里面会有一些为其他语种提供翻译,而你的app又不需要这个语种的翻译,而且这个库里面还包含了我的app中不支持的 mdpi 资源文件。

    还好从Android Gradle Plugin 0.7 开始,你可以配置你的app的build系统。这主要是通过配置 resConfig 和 resConfigs 以及默认的配置选项。下面的 DSL (Domain Specific Language)就会阻止 aapt(Android Asset Packaging Tool)打包app中不需要的资源文件。

    defaultConfig {
        // ...
    
        resConfigs "en", "de", "fr", "it"
        resConfigs "nodpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi"
    }

    你也可以用这个方式:

    Density Splits

    android {
      ...
      splits {
        density {
          enable true
          exclude "ldpi", "tvdpi", "xxxhdpi"
          compatibleScreens 'small', 'normal', 'large', 'xlarge'
        }
      }
    enable: enables the density split mechanism
    exclude: By default all densities are included, you can remove some densities.
    include: indicate which densities to be included
    reset(): reset the list of densities to be included to an empty string (this allows, in conjunctions with include, to indicate which one to use rather than which ones to ignore)
    compatibleScreens: indicates a list of compatible screens. This will inject a matching <compatible-screens><screen ...> node in the manifest. This is optional.
     
    Note that this will also always generate a universal APK with all the densities.
     

    ABIs Splits

    android {
      ...
      splits {
        abi {
          enable true
          reset()
          include 'x86', 'armeabi-v7a', 'mips'
          universalApk true
        }
      }
    }
    enable: enables the ABIs split mechanism
    exclude: By default all ABIs are included, you can remove some ABIs.
    include: indicate which ABIs to be included
    reset(): reset the list of ABIs to be included to an empty string (this allows, in conjunctions with include, to indicate which one to use rather than which ones to ignore)
    universalApk: indicates whether to package a universal version (with all ABIs) or not. Default is false.
     
     

    详细请参考:http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits

    一个完整的例子:https://android.googlesource.com/platform/tools/base/+/2101d189d85dd46f865726b9b7aa0012832a6d9c/build-system/tests/regular/densitySplit/build.gradle

    参考自:

    http://zmywly8866.github.io/2015/04/06/decrease-apk-size.html

    http://hukai.me/android-tips-for-reduce-apk-size/

    http://hao.jser.com/archive/1634/

    http://stackoverflow.com/questions/20599840/gradle-builds-for-every-resource-folder

  • 相关阅读:
    JAVA日报
    JAVA日报
    JAVA日报
    JAVA日报
    leetcode刷题笔记 260题 只出现一次的数字 III
    leetcode刷题笔记 241题 为运算表达式设计优先级
    leetcode刷题笔记 258题 各位相加
    leetcode刷题笔记 257题 二叉树的所有路径
    leetcode刷题笔记 242题 有效的字母异位词
    leetcode刷题笔记 240题 搜索二维矩阵 II
  • 原文地址:https://www.cnblogs.com/tianzhijiexian/p/4505312.html
Copyright © 2011-2022 走看看