android--App启动性能优化

一、应用的启动方式

  • 1、冷启动:当应用启动时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用,这种启动方式就是冷启动。

  • 2、热启动:当应用启动时,后台已有该进程的应用(例:按back键、Home键、应用虽然会退出,但是该应用的进程依然保留在后台,可进入任务列表查看),这种情况下直接启动该应用,这种方式就是热启动。

  • 3 、首次启动:首次启动严格来说也是冷启动,之所以把首次启动单独列出来,一般来说,首次启动时间会比非首次启动要久,首次启动会做一些系统初始化工作,如缓存目录的生产,数据库的建立,SharedPreference的初始化,如果存在多 dex 和插件的情况下,首次启动会有一些特殊需要处理的逻辑,而且对启动速度有很大的影响,所以首次启动的速度非常重要,毕竟影响用户对 App 的第一印象。

特点
  • 1、冷启动:因为系统会重新创建一个新的进程分配给它,所以会先创建和初始化Application类,再创建和初始化第一个页面(包括一系列的测量、布局、绘制),最后显示在界面上。

  • 2、热启动:因为会从已有的进程中来启动,所以热启动就不会走Application这一步,而是直接初始化第一个页面,所以热启动的过程只需要创建和初始化一个首页就可以了,而不需要创建和初始化Application,因为一个应用从新进程的创建到进程的销毁,Applicaiton只会初始化一次。

二、应用的启动流程

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

Application的构造器方法——>attachBaseContext()——>onCreate()——>Activity的构造方法——>onCreate()——>配置主题中背景等属性——>onStart()——>onResume()——>测量布局绘制显示在界面上
大致流程如下:

1、点击桌面图标,Launcher会启动程序默认的Acticity,之后再按照程序的逻辑启动各种Activity

2、启动Activity都需要借助应用程序框架层的ActivityManagerService服务进程(Service也是由ActivityManagerService进程来启动的);在Android应用程序框架层中,ActivityManagerService是一个非常重要的接口,它不但负责启动Activity和Service,还负责管理Activity和Service。

第一步: 无论是通过Launcher来启动Activity,还是通过Activity内部调用startActivity接口来启动新的Activity,都通过Binder进程间通信进入到ActivityManagerService进程中,并且调用ActivityManagerService.startActivity接口。

第二步:ActivityManagerService调用ActivityStack.startActivityMayWait来做准备要启动的Activity的相关信息。

第三步:ActivityStack通知ApplicationThread要进行Activity启动调度了,这里的ApplicationThread代表的是调用ActivityManagerService.startActivity接口的进程,对于通过点击应用程序图标的情景来说,这个进程就是Launcher了,而对于通过在Activity内部调用startActivity的情景来说,这个进程就是这个Activity所在的进程了。

第四步:ApplicationThread不执行真正的启动操作,它通过调用ActivityManagerService.activityPaused接口进入到ActivityManagerService进程中,看看是否需要创建新的进程来启动Activity。

第五步:对于通过点击应用程序图标来启动Activity的情景来说,ActivityManagerService在这一步中,会调用startProcessLocked来创建一个新的进程,而对于通过在Activity内部调用startActivity来启动新的Activity来说,这一步是不需要执行的,因为新的Activity就在原来的Activity所在的进程中进行启动。

第六步:ActivityManagerServic调用ApplicationThread.scheduleLaunchActivity接口,通知相应的进程执行启动Activity的操作。

第七步: ApplicationThread把这个启动Activity的操作转发给ActivityThread,ActivityThread通过ClassLoader导入相应的Activity类,然后把它启动起来。

App启动时间

为了对App启动性能进行正确的评估,启动时间这一指标就显得尤为重要。App的启动时间指的是从点击应用的启动图标开始到我们看到了界面的第一帧这段时间

  • 系统提供的启动时间方案

    自Android 4.4之后,logcat新增一个输出,关键字叫Displayed,这个关键字可以粗略的提现App启动时间,在log日志中查看叫  Displayed   日志  过滤一定要是  NoFilters
    
  • ADB命令提供的启动时间方案

    adb shell am start -W 应用包名/页面的全路径
    
    示例:adb shell am start -W com.pf.test/com.pf.test.activity.SplashActivity
    
    adb shell dumpsys activity activities
    
    am 命令在Android源码的\android-6.0.0_r1\android-6.0.0_r1\frameworks\base\cmds\am\src\com\android\commands\am\Am.java
    

这里写图片描述

此法获取的启动时间非常精准,可精确到毫秒。
● ThisTime: 最后一个启动的Activity的启动耗时
● TotalTime: 自己的所有Activity的启动耗时
● WaitTime: ActivityManagerService启动App的Activity时的总时间(包括当前Activity的onPause()和自己Activity的启动)

冷启动时间是指当用户点击你的app那一刻到系统调用Activity.onCreate()之间的时间段。在这个时间段内,WindowManager会先加载app主题样式中的windowBackground做为app的预览元素,然后再真正去加载activity的layout布局

利用TraceView分析启动时间

TraceView是什么,TraceView是Android平台特有的数据采集和分析工具,主要用做热点分析,找出最需要优化的点。TraceView从代码层面分析性能问题,针对每个方法来分析,比如当我们发现自己的App出现卡顿的时候,可以用它来分析出现卡顿时在方法中有没有很耗时的操作。

通过TraceView,可以得到两组很重要的数据:

单次执行最耗时的方法

执行次数最多的方法

这里写图片描述

  • 采集数据的方式有两种,

    • 第一种是通过代码来得到traceview文件,你可以直接在需要统计的代码部分头尾设置,比如我这里是统计application中的onCreate方法

这里写图片描述

生成的traceview文件会自动放在SDCARD上,没有SDCARD卡会出现异常,所以使用这种方式需要确保应用的AndroidMainfest.xml中的SD卡的读写权限是打开的,其中aizuna.trace是traceview文件的名字,然后用adb导出traceview文件。

导出trace文件:adb pull /storage/sdcard0/apf.trace F:\test

将导出的trace文件直接拖入AndroidStudio即可分析
  • 使用Android Device Monitor打开traceview

    在Android Device Monitor 界面,先选择应用进程,然后点击Start Method Profiling(开启方法分析),按钮会变为Stop Method Profiling(停止方法分析),开启方法分析后,对应用的目标页面进行测试操作,测试完毕后停止方法分析,界面会自动跳转到DDMS的trace分析界面。
    

两种方式的对比:
第一种方式更精确到方法,起点和终点都是自己定,不方便的地方是自己需要添加方法并且要导出文件,第二种方式的优缺点刚好相反。

启动优化

  • 1、从Theme方面考虑

    可以在Manifest.xml中的application节点中的theme中添加颜色值或者drawable
        <item name="android:windowBackground">@mipmap/icon_no_history</item>
    

    这么做的缺点就是每个页面都会有这个背景,这个时候可以先搞一个theme,在activity的onCreate方法的super.onCreate(bundle);之前调用setTheme(R.style.xxx)
    将Theme中设置 true 上面那个是设置颜色,而这个是将颜色设置为透明,这样的话,用户打开app的前几秒钟可能会没有反应,但是这个时候app已经在启动了,只不过颜色是透明的,所以显示的是桌面。

  • 2、从代码方面考虑

    在application中尽量不要做过多的操作,如果要初始化第三方框架的话,可以将第三方框架封装一个工具类,在里面去初始化(假如要用图片加载框架,在loadImage方法中判断是否初始化了,没有的话再进行初始化,这样的话,第一张图片可能会慢一点,但是后面的就是很快的),而不用拖慢app的启动速度

    在activity中,布局尽量不要用嵌套太多层的layout,可以使用ViewStub等

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值