APP启动优化

Android是基于Linux的,每一个app都是一个独立的dalivk(4.4之后是art)虚拟机,每个虚拟机都是Linux中的一个独立进程,这样就保证了APP崩溃时,只是这一个虚拟机崩溃,而不会影响其它虚拟机

名词说明:

  • 进程:进程就是系统中正在运行的程序,进程是操作系统的概念,每当我们执行一个程序时,对于操作系统来讲就是创建了一个进程,
  • idle进程:系统创建的第一个进程,也是唯一一个不是fork出来的进程
  • init进程:init进程(1号进程)由0号进程(idle进程)创建,完成系统的初始化,是第一个用户进程,是其他所有用户进程的父进程
  • zygote进程:由init进程创建,负责后续Android应用程序框架层的其它进程的创建和启动工作,Android系统开启新进程的方式,是通过fork第一个zygote进程实现的
  • fork:fork函数UNIX及类UNIX系统中的分叉函数,一个现有进程可以调用fork函数创建一个新进程。由fork创建的新进程被称为子进程。fork函数被调用一次但返回两次。两次返回的唯一区别是子进程中返回0值而父进程中返回子进程ID。子进程是父进程的副本,它将获得父进程数据空间、堆、栈等资源的副本。注意,子进程持有的是上述存储空间的“副本”,这意味着父子进程间不共享这些存储空间。
  • SystemServer进程:由zygote进程创建,SystemServer进程会启动所有系统的核心服务,如包管理服务PMS和应用程序组件管理服务AMS,硬件相关的Service等。然后它开启一个Socket接口来监听请求, 根据请求fork新的VM来管理新的App进程. 一旦收到新的请求, Zygote会基于自身预先加载的VM来fork一个新的VM创建一个新的进程
  • AMS - ActivityManagerService :负责系统中 四大组件 的启动、切换、调度及应用程序的管理和调度等工作
  • PMS - PackageManagerService:负责系统中Package的管理,应用程序的安装、卸载、信息查询等,博客说明:PackageManagerService类作用分析_h55l55的专栏-CSDN博客
  • WMS - WindowManagerService:每个窗口都有一块Surface供自己涂鸦,所以需要对所有窗口的Surface进行协调管理,为所有窗口分配Surface,掌管Surface的显示顺序以及位置尺寸,控制窗口动画,并且还是输入系统的一个重要的中转站

笼统的开机过程:

手机开机-Linux启动,系统创建第一个进程-idle进程,由idle完成初始化操作,包括初始化页表,初始化中断向量表,初始化系统时间等。继而调用 fork(),创建第一个用户进程init进程,由init进程完成内核后续的初始化工作,并且会fork()一个zygote进程,负责后续Android应用程序框架层的其它进程的创建和启动工作,再由zygote进程fork()出一个SystemServer进程,这里主要会做的事情是

  1. 启动binder线程池,这是SystemServer与其他进程通信的基础
  2. 初始化Looper
  3. 创建SystemServiceManager对象,它会启动Android中的各种服务。包括AMS、PMS(PackageManagerService)、WMS(WindowManagerService)
  4. 启动桌面进程,这样才能让用户见到手机的界面。
  5. 开启loop循环,开启消息循环,SystemServer进程一直运行,保障其他应用程序的正常运行。

应用启动流程:

  1. 点击图标发生在Launcher应用的进程,startActivity()函数最终是由Instrumentation通过Android的Binder跨进程通信机制 发送消息给 SystemServer 进程; 在 SystemServer 中,启动进程的操作由ActivityManagerService 通过 socket 通信告知 Zygote 进程 fork 子进程(app进程)
  2. 开启主线程 app 进程启动后,首先是实例化 ActivityThread,并执行其main()函数:创建 ApplicationThread,Looper,Handler 对象,并开启主线程消息循环Looper.loop()。
  3. 创建并初始化 Application和Activity, ActivityThread的main()调用 ActivityThread#attach(false)方法进行 Binder 通信,通知SystemServer进程执行 ActivityManagerService#attachApplication(mAppThread)方法,用于初始化Application和Activity。 在SystemServer 进程中,ActivityManagerService#attachApplication(mAppThread)里依次初始化了Application和Activity,分别有2个关键函数: thread#bindApplication()方法通知主线程Handler 创建 Application 对象、绑定 Context 、执行 Application#onCreate() 生命周期 mStackSupervisor#attachApplicationLocked()方法中调用 ActivityThread#ApplicationThread#scheduleLaunchActivity()方法,进而通过主线程Handler消息通知创建 Activity 对象,然后再调用 mInstrumentation#callActivityOnCreate()执行 Activity#onCreate() 生命周期
  4. 布局&绘制

 到这里Android启动与APP启动大致做了一个说明,接下来做启动优化

启动可分为:

  • 冷启动 

        从点击应用图标到UI界面完全显示且用户可操作的全部过程。

  • 热启动

        直接从后台切换到前台。

  • 温启动

        只会重走Activity的生命周期,而不会重走进程的创建,Application的创建与生命周期等

虽然有三种,但我们的工作只有冷启动,因为热启动,我们不需要优化,温启动就看你们自己了,如果你非要在setContentView之前做大量的耗时操作,那我能说啥?

言归正传,看看我们能在什么地方做点什么?

冷启动

  • 启动App
  • 加载空白Window
  • 创建进程
  • 创建Application
  • 启动主线程
  • 创建MainActivity
  • 加载布局
  • 布置屏幕
  • 首帧绘制

从这个过程可以看到,我们能做且可控并需要优化的地方,也就是Application和Activity的生命周期了

我们做的是启动优化,你应该不会在首个Activity中就把布局做的超级复杂且冗长从而导致耗时过多,用户看不到你想给他看的页面吧?

我们先对启动做一个计时,在生命周期中也加上计时,这样你就可以知道总耗时和某一个方法的耗时,总耗时-生命周期耗时=系统启动耗时,如果系统启动耗时很久,说明你手机很烂,如果系统耗时小于生命周期耗时,说明你可以想办法优化一下

获取总耗时的方法:

Logcat

        在Android Studio Logcat中过滤关键字“Displayed”,可以看到对应的冷启动耗时日志

adb命令

adb shell am start -W 包名/AppStartActivity的全路径    如:com.seller.app.page.activity.SplashActivity

例子:

adb shell am start -W com.tencent.mobileqq/com.tencent.mobileqq.activity.SplashActivity

在log中有两个时间

TotalTime:应用的启动时间,其包括 创建进程 + Application初始化 + Activity初始化到界面显示 的过程

WaitTime:代表Ams启动activity的总耗时

这里我用了荣耀很烂的一个手机测试了qq

冷启动TotalTime不到600毫秒

热启动TotalTime不到200毫秒

而我建立了一个新的项目,什么都没有的情况下,TotalTime用时竟然不比qq的少甚至还要多一些😱,腾讯好屌,就这我还写个屁啊!

推荐两个博客个博客:

深入探索Android启动速度优化(上) - 掘金,他后面说的好多工具和方案,有兴趣的参考下吧

Android应用启动流程分析 - 掘金:启动流程分析

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值