启动优化


为什么要做启动优化

1、第一体验很重要

2、八秒定律:如果打开需要8秒钟那么用户就会放弃

冷启动是衡量的标准

冷启动流程
click->ipc-process.start->ActivityThread->bindApplication->LifeCycle->ViewRootImpl

优化方向

Application和Activity 生命周期方法是优化的方向 其他的地方其实无法干预

adb命令获取启动时间

adb shell am start -W packagename/首屏Activity

adb shell am start -W com.example.better/.MainActivity
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.example.better/.MainActivity }
Status: ok
Activity: com.example.better/.MainActivity
ThisTime: 364
TotalTime: 364
WaitTime: 374
Complete

WaitTime 表示AMS启动Activity的总耗时

TotalTime 表示所有Activity启动耗时

ThisTime 表示最后一个Activity启动耗时

手动打点

就是从开始时间到ui展示出来的时比如你从application 开始到View画出来时间

比如创建一个类来负责记录时间


class LauncherTimer {
    private static long sTime;
    public static void startRecord() {
        sTime = System.currentTimeMillis();
    }
    public static void endRecord() {
        long cost = System.currentTimeMillis() - sTime;
        Log.i("cost", "endRecord: " + cost);
    }
}

需要注意的是,应该是View绘制出来作为结束时间,比如可以监听某个View绘制的时候作为结束时间


findViewById(R.id.text).getViewTreeObserver().addOnPreDrawListener(() -> {
           LauncherTimer.endRecord();
           return true;
       });

工具选择

1、Traceview

使用方式

Debug.startMethodTracing("app");

Debug.stopMethodTracing();

它会在应用的目录上生成一个xx.trace 文件 通过Studio打开后可以发现大概长这样

trace

上面滑动部分是你需要选中的时间范围

中间部分会列出所有线程,还有每个做了什么事情,也就是方法调用栈
点击方法可以知道每个方法的耗时
total就是这个方法的耗时,
children 就是子方法的耗时
self 就是自己花费了多长时间
知道了这些就可以进行性能优化

多关注TopDown就可以知道哪些方法耗时了

这个工具比价适合去做开机启动优化,因为开始和结束已经埋在代码里面了。

2、systemtrace

这个应用更适合去做一下某些操作的卡顿

使用方式

TraceCompat.beginSection("better");
TraceCompat.endSection();

运行后执行

python /Users/weihuada/Downloads/platform-tools/systrace/systrace.py -b 32768 -t 5 -a com.example.better -o performance.html sched gfx view wm am app

这个方法是 platform-tools里面自带的方法

这个方法在后续被google移除掉了
https://www.jianshu.com/p/626eaebaa6a8

执行后会输出 performance.html 到当前目录

然后通过浏览器 输入
chrome://tracing/
然后打开这个文件就可以了

启动优化的核心思想是异步优化,让子线程分担主线程任务,并行减少同步事件

但是要注意代码的执行先后顺序
有些代码是不能运行在异步线程的

我们可以用CountDownLatch 这个类去处理代码的先后执行顺序的问题
我们可以比如开四条线程,最后100秒的主线程被分隔到4条线程中
每条线程最后就是25秒 用这个CountDownLatch 就是能先阻塞住
等到四条线程都处理完了再进行下面的操作 但是它不能解决不同线程之间的同步问题
为了解决线程之间的同步问题 我们可以引入线程执行器这里就不展示具体代码。

将不重要的操作放到ui展示出来之后再初始化。

优化总方针

异步、延迟、懒加载

其他黑科技

启动时抑制GC

CPU锁频


  TOC