Android应用启动时间优化

       本篇是我在项目中对应用启动时间优化的一个总结。同时也参考了其他大神的文章。主要针对没有设置广告引导页的Android应用,这种Android应用的启动时间一般都要求比较高。否则就会影响用户体验。

目录

1.安卓应用的启动方式。

2.应用冷启动的流程

3.如何测试应用的启动时间

4.如何减少应用冷启动的耗时

5.相关的优化操作

5.1 使用StubView延迟加载策略

5.2 使用IdleHandler执行必要的主线任务


1.安卓应用的启动方式。

安卓应用的启动方式分为冷启动和热启动两种。

1、冷启动:启动应用时,系统中不存在此应用的进程;需要系统先去创建一个新的进程分配给该应用。因为创建一个新的进程,所以会先初始化Application类,再初始化MainActivity类。这种启动方式就是冷启动。

2、热启动:启动应用时,系统中已有该应用的进程(如按back键、home键,该应用的进程是依然会保留在后台),不必创建和初始化Application,而是初始化MainActivity,这个方式叫热启动。

本篇只总结冷启动的优化。

2.应用冷启动的流程

在安卓系统上,应用在没有进程的情况下,应用的启动都是这样一个流程:当点击app的启动图标时,安卓系统会从Zygote进程中fork创建出一个新的进程分配给该应用,之后会依次创建和初始化Application类、创建MainActivity类、加载主题样式Theme中的windowBackground等属性设置给MainActivity以及配置Activity层级上的一些属性、再inflate布局、当onCreate/onStart/onResume方法都走完了后最后才进行contentView的measure/layout/draw显示在界面上,所以直到这里,应用的第一次启动才算完成,这时候我们看到的界面也就是所说的第一帧。

所以,总结一下,应用的冷启动流程如下:

Application——>attachBaseContext()——>onCreate()——>Activity——>onCreate()——>onStart()——>onResume()——>显示。

3.如何测试应用的启动时间

可以通过adb shell命令的方式进行测量,这种方法测量的最为精确,命令:

adb shell am start -W [packageName]/[packageName.MainActivity]

执行成功后将返回三个测量到的时间: 
1、ThisTime:一般和TotalTime时间一样,除非在应用启动时开了一个透明的Activity预先处理一些事再显示出主Activity,这样将比TotalTime小。 
2、TotalTime:应用的启动时间,包括创建进程+Application初始化+Activity初始化到界面显示。 
3、WaitTime:一般比TotalTime大点,包括系统影响的耗时。

4.如何减少应用冷启动的耗时

针对冷启动的流程,主要采取以下策略: 
1、优化Application,在Application的构造器方法、attachBaseContext()、onCreate()方法中不要进行耗时操作,耗时操作尽量放在异步线程中,采取Callable实现。 
2、优化数据库初始化,数据库的初始化都是比较耗时的,所以放在主线程中会延迟应用的启动速度,还是需要放在异步线程中处理。 
3、优化MainActivity,由于在获取到第一帧前,需要对contentView进行测量布局绘制操作,尽量减少布局的层次,通过StubView的延迟加载策略;尽量减少在onCreate()、onStart()、onResume方法中执行主线程逻辑,可以将必须在主线程执行的低优先级任务放到IdleHandler中执行。

5.相关的优化操作

5.1 使用StubView延迟加载策略

ViewStub 是一个轻量级的View,它一个看不见的,不占布局位置,占用资源非常小的控件。可以为ViewStub指定一个布局,在Inflate布局的时候,只有 ViewStub会被初始化,然后当ViewStub被设置为可见的时候,或是调用了ViewStub.inflate()的时候,ViewStub所指向的布局就会被Inflate和实例化,然后ViewStub的布局属性都会传给它所指向的布局。我们可以使用ViewStub来延迟加载某个布局。

5.2 使用IdleHandler执行必要的主线任务

android主线程looper是在ActivityThread.java的main函数实例化的, 主线程使用一个MessageQueue实例,当消息过多或者消息执行周期比较长就会造成UI卡顿。

IdleHandler的作用是监听到MessageQueue中空闲(即onResume()执行完,绘制完成以后)的时候会回调queueIdle(),该方法返回一个boolean值,如果为false则执行完毕之后移除这条消息, 如果为true则保留,等到下次空闲时会再次执行。

 

欢迎指出本文中的不足之处,然后大家一起讨论。

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值