Android启动优化

启动优化的方式

  • 闪屏页优化
  • MultiDex优化(本文重点)
  • 第三方库懒加载
  • WebView优化
  • 线程优化
  • 系统调用优化

闪屏页优化

给启动页activity或者application设置窗口背景主题


MultiDex 优化

apk编译流程
  1. 打包资源文件,生成R.java文件(使用工具AAPT)
  2. 处理AIDL文件,生成java代码(没有AIDL则忽略)
  3. 编译 java 文件,生成对应.class文件(java compiler)
  4. .class 文件转换成dex文件(dex)
  5. 打包成没有签名的apk(使用工具apkbuilder)
  6. 使用签名工具给apk签名(使用工具Jarsigner)
  7. 对签名后的.apk文件进行对齐处理,不进行对齐处理不能发布到Google Market(使用工具zipalign)
classLoader加载类原理
ClassLoader.loadClass -> DexPathList.loadClass -> 
遍历dexElements数组 ->DexFile.loadClassBinaryName

ClassLoader加载类的时候是通过遍历dex数组,从dex文件里面去加载一个类,加载成功就返回,加载失败则抛出Class Not Found 异常。

MultiDex原理

反射dexElements数组,将新增的dex添加到数组后面,这样就保证ClassLoader加载类的时候可以从新增的dex中加载到目标类

MultiDex 优化(两种方案)

install过程为什么耗时,因为涉及到解压apk取出dex、压缩dex、将dex文件通过反射转换成DexFile对象、反射替换数组

方案1:子线程install(不推荐)

这个方法大家很容易就能想到,在闪屏页开一个子线程去执行MultiDex.install,然后加载完才跳转到主页。需要注意的是闪屏页的Activity,包括闪屏页中引用到的其它类必须在主dex中,不然在MultiDex.install之前加载这些不在主dex中的类会报错Class Not Found。
这个可以通过gradle配置,如下:

  defaultConfig {
        //分包,指定某个类在main dex
        multiDexEnabled true
        multiDexKeepProguard file('multiDexKeep.pro') // 打包到main dex的这些类的混淆规制,没特殊需求就给个空文件
        multiDexKeepFile file('maindexlist.txt') // 指定哪些类要放到main dex
    }

maindexlist.txt 文件指定哪些类要打包到主dex中,内容格式如下

com/lanshifu/launchtest/SplashActivity.class
方案2:今日头条的启动优化
  1. 在Application 的attachBaseContext 方法里,启动另一个进程的LoadDexActivity去异步执行MultiDex逻辑,显示Loading。
  2. 然后主进程Application进入while循环,不断检测MultiDex操作是否完成
    3.MultiDex执行完之后主进程Application继续走,ContentProvider初始化和Application onCreate方法,也就是执行主进程正常的逻辑

第三方库懒加载

很多第三方开源库都说在Application中进行初始化,十几个开源库都放在Application中,肯定对冷启动会有影响,所以可以考虑按需初始化,例如Glide,可以放在自己封装的图片加载类中,调用到再初始化,其它库也是同理,让Application变得更轻。

WebView启动优化。

WebView启动优化文章也比较多,这里只说一下大概优化思路。

  1. WebView第一次创建比较耗时,可以预先创建WebView,提前将其内核初始化。
  2. 使用WebView缓存池,用到WebView的地方都从缓存池取,缓存池中没有缓存再创建,注意内存泄漏问题。
  3. 本地预置html和css,WebView创建的时候先预加载本地html,之后通过js脚本填充内容部分。

数据预加载

这种方式一般是在主页空闲的时候,将其它页面的数据加载好,保存到内存或数据库,等到打开该页面的时候,判断已经预加载过,直接从内存或数据库读取数据并显示

线程优化

线程是程序运行的基本单位,线程的频繁创建是耗性能的,所以大家应该都会用线程池。单个cpu情况下,即使是开多个线程,同时也只有一个线程可以工作,所以线程池的大小要根据cpu个数来确定。

你可能感兴趣的:(Android启动优化)