一、应用的启动方式:
1、冷启动:当启动应用时,后台没有该应用的进程,这时系统会首先会创建一个新的进程分配给该应用,这种启动方式就是冷启动。
2、热启动:当启动应用时,后台已有该应用的进程,比如按下home键,这种在已有进程的情况下,这种启动会从已有的进程中来启动应用,这种启动方式叫热启动。
3、温启动 :当启动应用时,后台已有该应用的进程,但是启动的入口Activity被干掉了,比如按了back键,应用虽然退出了,但是该应用的进程是依然会保留在后台,这种启动方式叫温启动。
二、应用的启动时间统计:
adb shell am start -W [PackageName]/[PackageName.MainActivity]
执行成功后将返回三个测量到的时间:
三、性能检查项:
从我们Application开始到首页显示出来,这个过程,我们应该注意一些什么,将这个过程细分一下,会有下面的时间点需要注意。
Application的构造器方法——>attachBaseContext()——>onCreate()——>Activity的构造方法——>onCreate()——>配置主题中背景等属性——>onStart()——>onResume()——>测量、布局、绘制显示在界面上。
因为上面这些阶段全部都是在主线程中执行的,任何不经意的操作都可能拖慢应用的启动速度。所以我们不应在Application以及Activity的生命周期回调中做任何费时操作,具体指标大概是你在onCreate,onResume,onStart等回调中所花费的总时间最好不要超过400ms,否则用户在桌面点击你的应用图标后,将感觉到明显的卡顿。但是有些不得以的任务又必须在UI显示之前执行。所以我们要将任务划分优先级。
- 优先级为1的在应用启动时,就开始加载
- 优先级为2的在首页渲染完成后,开始加载
- 优先级为3的在首页渲染完成后,延迟加载
优化的DelayLoad getWindow().getDecorView().post(new Runnable() { @Override public void run() { myHandler.post(mLoadingRunnable); } });
四、检测界面是否有掉帧:
在Choreographer类中有如下代码:
void doFrame(long frameTimeNanos, int frame) { final long startNanos; synchronized (mLock) { if (!mFrameScheduled) { return; // no work to do } if (DEBUG_JANK && mDebugPrintNextFrameTimeDelta) { mDebugPrintNextFrameTimeDelta = false; Log.d(TAG, "Frame time delta: " + ((frameTimeNanos - mLastFrameTimeNanos) * 0.000001f) + " ms"); } long intendedFrameTimeNanos = frameTimeNanos; startNanos = System.nanoTime(); final long jitterNanos = startNanos - frameTimeNanos; if (jitterNanos >= mFrameIntervalNanos) { final long skippedFrames = jitterNanos / mFrameIntervalNanos; if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) { Log.i(TAG, "Skipped " + skippedFrames + " frames! " + "The application may be doing too much work on its main thread."); } final long lastFrameOffset = jitterNanos % mFrameIntervalNanos; if (DEBUG_JANK) { Log.d(TAG, "Missed vsync by " + (jitterNanos * 0.000001f) + " ms " + "which is more than the frame interval of " + (mFrameIntervalNanos * 0.000001f) + " ms! " + "Skipping " + skippedFrames + " frames and setting frame " + "time to " + (lastFrameOffset * 0.000001f) + " ms in the past."); } frameTimeNanos = startNanos - lastFrameOffset; }
static { try { Field field = Choreographer.class.getDeclaredField("SKIPPED_FRAME_WARNING_LIMIT"); field.setAccessible(true); field.set(Choreographer.class,1); } catch (Throwable e) { e.printStackTrace(); } }
01-26 15:31:16.194 8743 8743 I Choreographer: Skipped 2 frames! The application may be doing too much work on its main thread. 01-26 15:31:16.269 8743 8743 I Choreographer: Skipped 3 frames! The application may be doing too much work on its main thread. 01-26 15:31:19.730 8743 8743 I Choreographer: Skipped 31 frames! The application may be doing too much work on its main thread. 01-26 15:31:19.751 8743 8743 I Choreographer: Skipped 1 frames! The application may be doing too much work on its main thread.