启动流程
1.点击桌面图标,Launcher进程采用Binder IPC向system_server进程发起startActivity请求
2.system_server进程接收到请求后,向zygote进程发送创建进程的请求
3.Zygote进程fork出新的子进程,即App进程
4.App进程通过Binder IPC向system_server进程发起attachApplication请求
5.system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向App进程发送scheduleLaunchActivity请求
6.App进程的binder线程在收到请求后,通过hander向主线程发送LAUNCH_ACTIVITY消息
7.主线程收到消息后,通过反射机制创建目标Activity,并回调Activity的onCreate()方法
8.App正式启动,开始Activity的生命周期
冷启动
- 什么是冷启动
1.冷启动定义
冷启动就是在启动应用前,系统中没有该应用的任何进程信息。
(也就是第一次打开该应用、或者该应用进程被杀死再次打开的时候)
2.冷启动、热启动的区别
热启动:用户使用返回键退出应用(应用的进程被保留在后台),然后马上又
重新启动应用。
冷启动的时候,系统会给该应用进程重新分配内存,创建初始化Applicatio
n,再对MainActivity进行测量布局等一系列操作。
热启动的时候,对MainActivity进行测量布局等一系列操作。
热启动会较快的进入应用,冷启动会有一段白屏时间。
3.冷启动时间的计算
这个时间值从应用启动(创建进程)开始计算,到完成视图的第一次绘制(
即activity内容对用户可见)为止。
根据具体的业务不同,很难说一个App启动多久才算比较好,但是我们采用Google的标准
认为控制在5s内就算比较好
4.冷启动时间统计
as里日志有个displayed
或者 adb shell am start -S -W [包名]/[activity名]
上面adb命令启动的应用会显示三个值:
ThisTime:最后一个Activity的启动耗时
TotalTime:新应用启动的耗时【我们主要关注这个就可以了】
WaitTime:包括前一个应用activity pause的时间和新应用启动的时间
CPU Profile的使用
Traceview是android平台配备一个很好的性能分析的工具。它可以通过图形化的方式让我们了解我们要跟踪的程序的性能,并且能具体到每个方法的执行时间。但是目前Traceview 已弃用。如果使用 Android Studio3.2 或更高版本,则应改为使用 CPU Profiler
类型 | 作用 |
---|---|
Call Chart | 根据时间线查看调用栈,便于观察每次调用是何时发生的 |
Flame Chart | 根据耗时百分比查看调用栈,便于发现总耗时很长的调用链 |
Top Down Tree | 查看记录数据中所有方法调用栈,便于观察其中每一步所消耗的精确时间 |
Bottom Up Tree | 便于观察耗时方法如何被调用的 |
CPU Profiler需要使用在8.0及以上版本,那么其他版本的呢?我们可以借助Debug API在指定目录生成trace文件。
public class MyApplication extends Application{
publicMyApplication() {
//跟踪模式 这个还是比较卡
// Debug.startMethodTracing("enjoy");
//可以用采样的方式
//参数二采样数据大小上限 参数三采样周期1ms
// Debug.startMethodTracingSampling("xxxxxxxx",8*1024*1024,1_000);
}//.....
}
public class MainActivity extends AppCompatActivity{
@Override
public void onWindowFocusChanged(booleanhasFocus){
super.onWindowFocusChanged(hasFocus);
Debug.stopMethodTracing();
}//.......
}
运行App,则会在sdcard中生成一个enjoy.trace文件(需要sdcard读写权限)。将手机中的trace文件保存至电脑,随后拖入Android Studio即可。
冷启动的优化
根据上面冷启动的概念,我们可以知道,其实优化冷启动的工作主要得在Application和MainActivity里面。
1.减少onCreate()方法的工作量
我们重写Application的onCreate()方法,一般在里面初始化很多第三方的
框架,这就比较耗时。可以懒加载,等真正使用的时候再初始化,但就比较
麻烦。所以两者权衡一下。
2.不要让Application参与业务操作。
3.不在Application做耗时操作。比如加载大量文件、读流。
4.不要以静态变量的方式在Application中保存数据。
5.setContentView(R.layout.xxx)很耗时,所以要优化xml布局文件。
StrictMode
StrictMode常用于捕捉应用程序主线程上的意外磁盘或网络访问。帮助我们让磁盘和网络操作远离主线程,可以使应用程序更加平滑、响应更快。
//开发测试过程中开启,正式上线需要关闭
StrictMode.setThreadPolicy(//线程检查策略
new StrictMode.ThreadPolicy.Builder()
.detectDiskReads() //检查读写操作
.detectDiskWrites()
.detectNetwork()
.penaltyDeath()
.penaltyLog()
.build()
);
StrictMode.setVmPolicy(//VM检查策略
new StrictMode.VmPolicy.Builder()
.detectLeakedClosableObjects() //未关闭closable
.detectLeakedSqlLiteObjects() //sqlite泄露
.penaltyLog() //违规打印日志
.penaltyDeath() //违规的崩溃
.build()
);
启动黑白屏问题
不管怎样,app的启动总会需要时间,而这段时间又不能什么也没有反应,所以goole在这段时间会显示一个黑(白)屏,具体是黑屏还是白屏根据我们的主题AppTheme而定,那么解决这个黑白屏问题(让用户体验更好)呢?可以在这段时间展示我们的一张图片。
1.自定义主题
<style name="AppTheme.Launcher">
<item name="android:windowBackground">@drawable/liyifeng1</item>
<item name="android:windowFullscreen">true</item>
</style>
//我们担心图片变形,所以可以用.9图,也可以在drawable写一个xml文件,将图片居中就好了。
2.在第一个activity使用
<activity android:name="cn.gxh.base.SplashActivity"
android:theme="@style/AppTheme.Launcher">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
3.在第一个activity的onCreate()方法里再设置回原来的主题
setTheme(R.style.AppTheme)