冷启动优化

冷启动优化主要优化两个方面

  • Application 性能优化
  • App启动页性能优化
    业务优化不在本章优化范围内。本章主要量化性能检测数据和问题,并针对其做性能优化和修改。

冷启动速度优化

冷启动耗时统计
adb shell am start -S -W [packageName] / [activityName]
  • -s 表示杀死程序重启
  • -w 启动并输出相应的数据
  • packageName applicationId
  • activityName 启动页的名称,Luauncher Activity

执行上述命令,成功唤起应用,并在控制台输出如下数据:


image.png

LaunchState : 启动模式,这里是冷启动
waitTime:系统启动耗时 = TotalTime +系统资源时间
totalTime:应用自身启动时间 = 该Activity启动 + Application系统资源启动时间

对于冷启动,我们一般关注的是totalTime,该时间大致概括为:Application的onCreate到Activity的onWindowFouchChange方法的总和,这个初步理解为从应用启动到Activity获取焦点,业务执行的总时间。

冷启动耗时堆栈观察方法

在API>=26的版本中,建议使用CPU profile 或者Debug.startMethodTracing进行监控导出trace文件。

  • CPU profile
    这种方式不知道冷启动怎么监控,但是可以手动采样启动后某一段时间。


    image.png
  • Debug.startMethodTracing
    由于冷启动涉及到业务应用层面是:Activity启动+Application系统资源启动时间。所以,我们在Application中开始采集,在第一个Activity的onWindowFouchChange里面停止采集,并输出trace文件。
//Application 的onCreate代码
 fun  applicationTrace(){
         // 保存trace的文件
         val file  =  File(Environment.getExternalStorageState(),"myApp.trace")
         //采集方式有两种,根据需要选择其一
         //通过采样的方式追踪堆栈信息

//         if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ){
//             //通过采样方式追踪堆栈信息,需要制定文件保存目录,文件大小 单位M,采样间隔时间us
//             Debug.startMethodTracing(file.absolutePath,8,1000)
//         }

         //第二种方式全采样
         Debug.startMethodTracing(file.absolutePath)

    }

//MainActivity的代码
   override fun onWindowFocusChanged(hasFocus: Boolean) {
        super.onWindowFocusChanged(hasFocus)
        Debug.stopMethodTracing()
    }
Trace日志文件的阅读

在导出.trace文件后,直接拖到android studio中,便可以对程序运行的堆栈进行分析。


trace.png

上图是trace文件打开后的效果,是基于CPU和线程的运行状况,针对启动优化,需要关注几个点:
(1)CPU运行时间轴,横向拖动可以选择时间范围。
(4)当前设备CPU轮转的线程:点击可以选择需要查看的线程,我们重点关注主线程
(2)当前选择线程,跟随时间轴各个方法栈的调用情况和耗时情况。其不同颜色分别代表:

  • 黄色 :android系统方法(Framwork层代码,如果需要最终最底层的方法,需要C/C++代码调用栈。
  • 蓝色:代表java JDK方法
  • 绿色:属于当前进程执行的方法,包括类加载器和我们的业务代码。(启动优化主要是这部分)
    (3)各个方法栈的调用顺序和耗时情况。可以选择不用的排序方式和视图。
Application优化

通过trace文件,我们发现,耗时最长的是Application的onCreate方法,其中initMudleFactory、initURS、Unicore.init、initUmeng都比较耗时。
查看这几个三方库初始化源码,发现都做了现场安全,所以直接放到子线程中执行。
对于一些不能放到子线程中执行的三方库的初始化,我们可以使用IdleHandle去处理,它会在主线程空闲的时候去执行。

Launcher Activity优化

思路还一样,查看trace文件,在Activity的onCreate中有三个地方耗时比较多,initActionbar,EventBus.register,setContentView。下面分别做优化:
1.initActionbar
通过trace图可以看到最耗时的是getSupportActionBar,实际的欢迎页面不需要actionBar,所以,我们重写了父类方法,把super方法去掉了。
2.EventBus.register
Eventbus2.0是通过注解加反射实现的,性能相对差,所以我们可以升级到3.0.这个是通过编译生成文件,不会对运行时性能造成影响。
3.setContentView

 AsyncLayoutInflater(this).inflate(
            R.layout.activity_welcome, null
        ) { view: View?, resid: Int, parent: ViewGroup? ->
            setContentView(
                view
            )
        }

通过异步加载布局是一个方面,优化布局是另一个方面。

优化方法总结

1.合理的使用异步加载、延迟初始化、懒加载机制去初始化三方库。
2.主线程中避免做耗时操作,比如io,数据的读写。
3.简化launcher Activity的布局,采用两种方式优化:

  • 采用ConstraintLayout减少布局的层数,降低过度渲染
  • 使用 androidx.asynclayoutinflater:asynclayoutinflater进行异步加载xml

4.合理的使用idleHandler进行延迟初始化

/**

 * 需要在当前线程中处理耗时任务,并且并不需要马上执行的话,可以使用IdleHandler

 * 这样该任务可以消息队列空闲时,被处理

 */

Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {

    @Override

    public boolean queueIdle() {

        //此处添加处理任务



        //返回值为false:则执行完毕之后移除这条消息,

        //返回值为true:则则执行完毕之后依然保留,等到下次空闲时会再次执行,

        return false;

    }

});

5.使用严苛模式(Strict Mode)
该模式并不能自动帮我们优化性能,但是可以检测出我们的代码或者三方库代码会阻塞Main线程的事情(例如磁盘操作,网络操作),并将他们提示出来,我们在开发阶段可以修改掉。

/**

 * 开启严苛模式,当代码有违规操作时,可以通过Logcat或崩溃的方式提醒我们

 */

private void startStrictMode() {

    if (BuildConfig.DEBUG) { //一定要在Debug模式下使用,避免在生产环境中发生不必要的崩溃和日志输出



        //线程检测策略

        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()

                .detectDiskReads()  //检测主线程磁盘读取操作

                .detectDiskWrites() //检测主线程磁盘写入操作

                .detectNetwork() //检测主线程网络请求操作

                .penaltyLog() //违规操作以log形式输出

                .build());



        //虚拟机检测策略

        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()

                .detectLeakedSqlLiteObjects() //检测SqlLite泄漏

                .detectLeakedClosableObjects() //检测未关闭的closable对象泄漏

                .penaltyDeath() //发生违规操作时,直接崩溃

                .build());

    }

}



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