对于Android来说,启动的速度是至关重要的,假如用户点击app图标开始,很长时间进不了app主界面,那么这是不能忍受的,可能会造成app卡死,所以这里对app启动优化做一个总结。
App启动流程:
1.点击桌面App图标,launcher进程采用Binder IPC向system_server进程发起startActivity()请求。
2.system_server进程接收到请求后,向zygote进程发送创建进程的请求
3.Zygote进程fork出新的子进程,即App进程。
4.App进程,通过Binder IPC向sytem_server进程发起attachApplication请求
5.system_server进程收到请求后,进行一系列准备工作后,再通过binder IPC向进程发送s cheduleLaunchActivity请求。
6.App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息
7.主线程在收到message后,通过反射机制创建目标Activity,并回调Activity.onCreate()等方法。
8.到此,App便正式启动,开始进入Activity生命周期,执行完onCreate/onStart/onResume方法,ui渲染结束后便可以看到App的主界面。
对App启动速度优化应该从Application到启动界面的onWindowFocusChanged()。
一.相关概念
冷启动,热启动,温启动
冷启动:冷启动是指应用从头开始启动,系统进程在冷启动后才创建应用进程,发生冷气功的情况包括应用自设备启动后或终止应用后首次启动
温启动:温启动包含了在冷启动期间发生的部分操作;同时,它的开销要比热启动高。有许多潜在状态可视为温启动
热启动:在热启动中,系统的所有工作就是将Activity带到前台,只要应用的所有Activity仍驻留在内存中,应用就不必重复执行对象初始化,布局加载和绘制
1.用户在退出应用后又重新启动应用。进程可能未被销毁,继续运行,但应用需要执行oNCreate()从头开始创建Activity
2.系统将应用从内存中释放,然后用户又重新启动它,进程和Activity需要重启,但传递到oncreate()的已经保存的实例saveInstanceSta te对于完成此任务有一定的助益。
针对冷启动:进行耗时计算:
(1) 查看日志:(过滤字段display)如下图:
(2) adb命令进行查看(adb shell am start -S -W [packageName]/[activityName])
提示:需要进行配置adb环境变量 主要看totalTime
二.工具的使用(CPU Profile)
首先进行相关配置
第一步:如图点击选择Edit Configurations
第二步:如图选择:(第一步后弹出如下框进行相关选择)
相关解释:sample java methods :对Java方法进行采样有可能某个方法采集不到,所以选择 trace java methods(跟踪采样)
第三步:如图选择Profile app运行
第四步 :运行结束 如图
第五步进行分析:
1.Call Chart :(橙色的表示系统的类,绿色自己写的类,蓝色) 根据时间线查看调用栈,便于观察每次调用是何时发生的
横条越长,表明花费的时长就越长。
这里能看到各个部分耗费的时间长,比如布局的加载:
onCreate()方法的加载:
application的加载时长:
2.Flame Chart 火焰图:(橙色的表示系统的类,绿色自己写的类,蓝色) 根据时间线查看调用栈,便于观察每次调用是何时发生的。根据耗时百分比查看调用栈,便于发现总耗时很长的调用栈
出现的图像:
也是看x轴的长度,越长耗时越长,调用顺序从下往上看。
3.Top Down :查看记录数据中所有方法调用栈,便于观察其中每一步所消耗的精确时间
一层一层看下去, total 耗时长是按照从大到小排列。一层一层往下查,更符合我们查找耗时的思维,我个人是比较喜欢这种的。
4.Bottom Up : 相对于Top Down Tree,能够更方便查看耗时方法如何被调用
展示的方式又不一样了。看一个一个方法,点进去才知道被谁调用了,比如dispatchMessage()是被main()调用的
Cpu Profile可能受版本限制,有些Android studio上可能没有这些功能。那只能代码进行操作了:
假如在低版本没有profile相关功能,我们也可以手动开启,在application中
在启动页关闭:
正常运行app:
查找Device File Explorer:
双击点开:就可以看到熟悉的图像了:
三.StrictMode(严苛模式)
是一个开发人员工具,它可以检测出我们可能无意中做的事情,并将它们提醒我们注意,以便我们能够修复它们
StrictMode最常用于捕获应用程序主线程上的意外磁盘或网络访问,帮助我们让磁盘和网络操作远离主线程,可以使应用程序更加平滑,反应更快。
代码编写在application:
MainActivity中
运行:
在开启了StrictMode后,磁盘读写在主线程中,这是不允许的,直接奔溃。这样可以使我们更直观和更规范的进行相关的开发工作。
最后启动速度优化应该注意几个点:
1.高耗时任务应该放入子线程中。
2.Application中不要做耗时操作,第三方sdk初始化能懒加载就懒加载
3.类不要过于复杂
4.view的层级不要太复杂
......