Skip to content Skip to footer

Android App启动流程全解析与性能分析优化实战

本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点

App启动流程

①点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起startActivity请求;

②system_server进程接收到请求后,向zygote进程发送创建进程的请求;

③Zygote进程fork出新的子进程,即App进程;

④App进程,通过Binder IPC向sytem_server进程发起attachApplication请求;

⑤system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向App进程发送scheduleLaunchActivity请求;

⑥App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息;

⑦主线程在收到Message后,通过反射机制创建目标Activity,并回调Activity.onCreate()等方法。

⑧到此,App便正式启动,开始进入Activity生命周期,执行完onCreate/onStart/onResume方法,UI渲染结束后便可以看到App的主界面。

启动状态

应用有三种启动状态,每种状态都会影响应用向用户显示所需的时间:冷启动、温启动与热启动。

温启动包含了在冷启动期间发生的部分操作;同时,它的开销要比热启动高

冷启动是指应用从头开始启动:系统进程在冷启动后才创建应用进程

在热启动中,系统的所有工作就是将 Activity 带到前台

启动优化一般是优化冷启动,一般冷启动时间大于5s就认为时间过长(官方)

启动时间查看

在logcat里,通过Display字段过滤,可以看到系统打印的启动时间日志

用adb查看App启动时间

adb shell am start -S -W [packageName]/[activityName]

一般会输入三个值:ThisTime、TotalTime与WaitTime。

一般关注TotalTime表示新应用启动的耗时,包括新进程的启动和Activity的启动,但不包括前一个应用Activity pause的耗时。

这个是统计到用户可操作的时间,也就是到onWindowFocusChanged的时间。

用IDE的CPU Profile功能来查看哪些步骤启动耗时

首先需要打开AS中的CPU Profile开关,在App的run configuration设置里,找到Profile,

然后打开

start this recording on startup,

选择

trace java methods

之后重启App,AS就会自动打开Profile

这个功能只支持API26以上的版本

Profile页面有一下4个tab

Call Chart

根据时间线查看调用栈,便于观察每次调用是何时发生的

Flame Chart

根据耗时百分比查看调用栈,便于发现总耗时很长的调用链

Top Down Tree

查看记录数据中所有方法调用栈,便于观察其中每一步所消耗的精确时间。

Bottom Up Tree

相对于Top Down Tree,能够更方便查看耗时方法如何被调用

此外,还可以用StrictMode模式检测耗时操作

//debug下开启StrictMode,检查耗时操作

if (BuildConfig.DEBUG){

//检查线程

StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder()

.detectDiskReads() //读写操作

.detectDiskWrites()

.detectNetwork() //检测网络

.penaltyLog() //检测到以后输出日志

.build())

//检查虚拟机

StrictMode.setVmPolicy(StrictMode.VmPolicy.Builder()

.detectLeakedSqlLiteObjects() //SQL泄漏操作

.detectLeakedClosableObjects() //未关闭的Closable

.penaltyLog() //检测到以后输出日志

.penaltyDeath() //违规奔溃

.build())

}

第三方框架启动耗时

EventBus、Arouter等

黑白屏问题优化

通过给启动的Activity设置一个主题style,这个主题设置windowbackground为一张启动图,可以优化体验;然后再activity的oncreate中把主题设置回来

对于API26以下的版本,我们可以通过手动触发CPU Profile

首先在application中启动,test表示生成的.trace文件名称

Debug.startMethodTracing("test")

然后在启动的入口activity的onWindowFocusChanged方法中停止

Debug.stopMethodTracing()

重新启动App以后会在SD卡上生成test.trace文件(App需要有读写SD卡权限),直接双击就可以在AS中打开了

总结

1). 合理的使用异步初始化、延迟初始化、懒加载机制。

2). 启动过程避免耗时操作,如数据库 I/O操作不要放在主线程执行。

3). 类加载优化:提前异步执行类加载。

4). 合理使用IdleHandler进行延迟初始化。

IdleHandler会在MessageQueue队列消息处理完以后空闲了回调

比如如果要在activity的View绘制完成之后再做些操作,就可以用IdleHandler;

onResume时View还没有绘制完成,onResume回调以后才会去执行performTraversals函数,也就是三大绘制流程

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

@Override

public boolean queueIdle() {

long time = System.currentTimeMillis();

//耗时操作

Log.i("tag", "cost time " + (System.currentTimeMillis() - time));

//false只执行一次,true会执行多次

return false;

}

});

5). 简化布局:

简化非必要的层级

注意一些自定义View里面是否有读写IO的情况,比如读写一些配置文件,字体文件等

欢迎关注我的公众号AntDream查看更多精彩文章!

Copyright © 2088 神州国际网游活动库 All Rights Reserved.
友情链接