启动优化

 

前言

以前有读者说到关于Android性能优化,性能优化包括不少方面,好比:php

启动优化、布局优化、内存优化、卡顿优化、网络优化、数据库优化、内存泄漏优化、包体积优化等等。java

后面咱们会依次聊聊,今天就从启动优化聊起android

冷启动、温启动、热启动

首先了解下启动的这三个概念,也是面试常被问到的:web

  • 冷启动。冷启动指的是该应用程序在此以前没有被建立,发生在应用程序首次启动或者自上次被终止后的再次启动。简单的说就是app进程尚未,须要建立app的进程并启动app。

好比开机后,点击屏幕的app图标启动应用。面试

冷启动的过程主要分为两步:数据库

1)系统任务。加载并启动应用程序;显示应用程序的空白启动窗口;建立APP进程 数组

2)APP进程任务。启动主线程;建立Activity;加载布局;屏幕布局;绘制屏幕缓存

其实这不就是APP的启动流程嘛?因此冷启动是会完整走完一个启动流程的,从系统到进程。性能优化

  • 温启动。温启动指的是App进程存在,但Activity可能由于内存不足被回收,这时候启动App不须要从新建立进程,只须要执行APP进程中的一些任务,好比建立Activity。

好比返回Home后,又继续使用其余的APP,时间久了或者打开的应用多了,以前应用的Activity有可能被回收了,可是进程还在。网络

因此温启动过程至关于执行了冷启动的第二过程,也就是APP进程任务,须要从新启动线程,Activity等。

  • 热启动。热启动就是指App进程存在,而且Activity对象仍然存在内存中没有被回收。

好比app被切到后台,再次启动app的过程。

因此热启动的开销最少,这个过程只会把Activity从后台展现到前台,无需初始化,布局绘制等工做。

优化点

三种启动方式中,冷启动经历的时间最长,也是走完了最完整的启动流程,因此咱们再次分析下冷启动的启动流程,看看有哪些能够优化的点:

  • Launcher startActivity
  • AMS startActivity
  • Zygote fork 进程
  • ActivityThread main()
  • ActivityThread attach
  • handleBindApplication
  • attachBaseContext
  • Application attach
  • installContentProviders
  • Application onCreate
  • Looper.loop
  • Activity onCreate,onResume

纵观整个流程,其实咱们能动的地方很少,无非就是Application的attach,onCreate方法,Activity的onCreate,onResume方法,这些方法也就是咱们的优化点。

优化方案

1)消除启动时的白屏/黑屏

App启动的时候会有一个白屏/黑屏时间,咱们能够经过设置windowBackground属性来给启动的Activity提供一个drawable,这样就给用户一个快递启动的假象了。

<activity ...
android:theme="@style/MyAppTheme" />

<style name="MyAppTheme" parent="Theme.AppCompat.NoActionBar">
    <item name="android:windowBackground">@drawable/logo</item> 
</style>

2)第三方库懒加载/异步加载

ApplicationonCreate方法中,总会有不少初始化操做,好比友盟,数据库,网络请求库,广告SDK等等。

对此,咱们能作的有哪些呢?

  • 异步加载。有些库不须要在主线程进行初始化,那么咱们就能够在子线程中进行初始化,进行异步加载。
  • 延迟加载。有些库没必要要一开始就初始化,咱们能够按需初始化,将一些库放到用它的时候再初始化,或者放到启动页去进行初始化。

因此须要咱们对这些初始化操做进行分析,哪些须要在主线程进行,哪些能够延迟加载,哪些初始化任务有前后关系等等。这里涉及到一个启动器的概念,启动器的用处就是能够充分利用CPU多核,自动梳理任务顺序。有空的朋友能够去了解下。

这里还须要注意一点就是线程的使用:

  • 即不要频繁建立线程,线程的频繁建立是耗性能的,因此须要用到 线程池去执行异步任务。

3)预建立Activity

Java中的对象第一次建立的时候,java虚拟机首先检查类对应的Class对象是否已经加载。若是没有加载,jvm会根据类名查找.class文件,将其Class对象载入。同一个类第二次new的时候就不须要加载类对象,而是直接实例化,建立时间就缩短了。

今日头条中就有这种作法,先建立一个Activity的实例。

4)预加载数据

在咱们的启动页或者主页能够将一些要用到的数据保存到内存或者数据库,那么其余页面要用到这些数据的时候就能够直接使用并显示了。

5)Multidex预加载优化

因为65536方法限制,因此通常class文件要生成多个dex文件,Android5.0如下,ClassLoader加载类的时候只会从class.dex(主dex)里加载,因此要执行MultiDex.install(context)方法才能正常读取全部的dex类。

而这个install方法就是耗时大户,会解压apk,遍历dex文件,压缩dex、将dex文件经过反射转换成DexFile对象、反射替换数组。

这里须要的方案就是今日头条方案:

  • 在Application的attachBaseContext方法里,启动另外一个进程的LoadDexActivity去异步执行MultiDex逻辑,显示Loading。

  • 而后主进程Application进入while循环,不断检测MultiDex操做是否完成 ,MultiDex执行完以后主进程Application继续执行ContentProvider初始化和Application onCreate方法,也就是主进程正常的逻辑。

因此重点就是单开进程去执行MultiDex逻辑,这样就不影响APP的启动了。

固然,这仅仅针对5.0如下加载Multidex状况,5.0以上默认使用ART加载类,安装时候就已经转换dex文件为oat文件了,因此无需优化Multidex状况了。

6)Webview启动优化

若是咱们的主页涉及到Webview,那咱们还要处理WebView的优化。由于Webview的建立很耗时,因此咱们采起如下方案进行Webview的优化:

  • 预先建立WebView,提早将其内核初始化。
  • 使用WebView缓存池,从缓存池中拿到Webview实例。
  • 本地提供静态页面资源。

7)避免布局嵌套

若是启动页和主页的布局比较复杂,也会影响咱们的启动时间,因此注意咱们的布局,多用merge,include,constraintlayout等,特别是多层嵌套问题。

总结

最后再和你们回顾下今天说到的启动优化方案:

  • 消除启动时的白屏/黑屏。windowBackground。
  • 第三方库懒加载/异步加载。线程池,启动器。
  • 预建立Activity。对象预建立。
  • 预加载数据。
  • Multidex预加载优化。5.0如下多dex状况。
  • Webview启动优化。预建立,缓存池,静态资源。
  • 避免布局嵌套。多层嵌套。

为了方便记忆,我再整理成如下三类,分别是Application、Activity、UI

  • Application 三方库,Multidex。
  • Activity 预建立类,预加载数据。
  • UI方面 windowBackground,布局嵌套,webview。

参考

 

 

感谢你们的阅读,有一块儿学习的小伙伴能够关注下公众号—码上积木❤️

每日三问知识点/面试题,聚沙成塔。

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

相关文章
相关标签/搜索