1、发动图
因此,咱们能够 整体的将运用发动分红三个阶段:
-
第一阶段:点击桌面Launcher运用的图标,通过与AMS(ActivityManagerService)通信,发动运用的进程。这段时刻,运用开发力不从心。
-
第二阶段:运用Application履行进程。这个阶段Applicaton会履行attachBaseContext(),会履行onCreate回调。这个时分是黑白屏。咱们再style的background能够放个图,给一种已经进入app的幻觉。
-
第三阶段:发动MainActivity履行进程。显现了运用的主要内容才算app发动完结。ActivityThread中有一个函数handleResumeActivity(),,这个函数调了onResume之后,有个wm.addView(decor,l)。也便是onResume()履行完之后,才会decorView显现到windows上。这个进程之后,
就进入到了可见可交互状况,用户才会觉得app已经运转起来了。
void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,String reason){
... 省略不需求的代码
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest,reason);// 这个里面会直接的调用activity的onResume 函数
...省略不需求的代码
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
wm.addView(decor, l); // 代码1
} else {
a.onWindowAttributesChanged(l);
}
}
...
}
2、优化方向
-
1、第一阶段的优化。主要是launcher和AMS交流,及AMS发动运用的进程,framework做得,咱没法动
-
2、第二阶段的优化。
- part1 attachBaseContext回调办法的优化。apk加固 热修正 等dex操作都在这儿处理,要分而治之。现在google对5.0及今后的多dex文件加载做了优化,暂时不必考虑。apk加固等天然生成需求时刻。优化方向便是要下降耗时尽量别加固
- part2 oncreate回调办法的优化。这个是中心。主要处理一些sdk、网络、数据库、SP等。依据业务需求,并不必定都要在这儿处理,依据业务需求,将一些不需求当即加载的库放到异步线程中区处理。
- 异步线程?那么jvm,线程切换的时刻怎么办理
- 运用线程池,每个sdk自己独立的线程池,如何处理?使命先后怎么处理》
- 有些使命必须在UIThread中初始化怎么办?
- 【用到的技术】拓扑排序图论 – ()、线程办理【待补充】、优先级办理【待补充】等技术、
- part3 运用履行到MainActivity之前的白屏处理
-
3、第三阶段的优化
- 第一个activity运转到OnResume函数履行完,才算履行完结。因此onCreate()\onStart()\onResume()都是需求优化的目标。
- onCreate()优化
- 1、布局优化,,简化布局用constraintLayout。
- 2、异步加载试视图 AsyncLayoutInflate
- 3、用composer,因为xml是反射加载的,速度比较慢一点。
- 4、掌阅的X2C,在编译时,生成布局java代码,就不必反射了。
- onStart/onPause
- 1、用缓存下,假如异步加载成功,会更新缓存。
- 2、初始化发动时,最好只用一个接口就拉去发动mainactivity和主activity所需数据。
- 3、懒加载,比方viewpager懒加载。
- 4、IdleHandler,把耗时使命丢到idleHandler里履行,进步速度。主线程没事做才会跑这个。
- 总结便是
- 合理运用异步初始化、延迟初始化、懒加载机制
- 发动进程比卖你耗时操作,比方 数据库I/O操作不要放在主线程履行
- 类加载优化:提前异步履行类加载
- 合理运用IdleHandler进行延迟初始化
- 简化布局
3、总结
-
App的发动耗时= app第一个activity 显现的时分(onWindowFocusChanged函数调用的时刻) — application 履行
-
要优化的点。1、application的attachBaseContext(),onCreate().Activity 的onCreate onstart onResume
4、苛刻模式
StrictModel是一个开发人员工具检测出咱们可能无意做的事情,并提醒咱们注意以便咱们能够修正她们。
public class MyApplication extends Application {
@Override
public void onCreate() {
if (BuildConfig.DEBUG) {
//线程检测策略
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads() //读、写操作
.detectDiskWrites()
.detectNetwork() // or .detectAll() for all detectable problems
.penaltyLog()
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects() //Sqlite目标走漏
.detectLeakedClosableObjects() //未关闭的Closable目标走漏
.penaltyLog() //违规打印日志
.penaltyDeath() //违规溃散
.build());
}
}
5、发动黑白屏
当体系加载并发动 App 时,需求耗费相应的时刻,这样会造成用户会感觉到当点击 App 图标时会有 “延迟” 现象。 为了解决这一问题,Google 的做法是在 App 创立的进程中,先展现一个空白页面,让用户体会到点击图标之后立 马就有响应
<style name="AppTheme.Launcher">
<item name="android:windowBackground">@drawable/bg</item>
</style>
<activity
android:name=".activity.SplashActivity"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.Launcher">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
然后在Activity的onCreate办法,把Activity设置回本来的主题
@Override
protected void onCreate(Bundle savedInstanceState) {
//替换为本来的主题,在onCreate之前调用
setTheme(R.style.AppTheme);
super.onCreate(savedInstanceState);
}
6、发动状况
- 冷发动
- 从头开始发动
- 热发动
- Activity仍驻在内存中,运用则不必重复履行目标初始化、布局加载和绘制
- 温发动
- 发动时刻介于两者之间,
- 用户退出运用后又重新发动运用,进程可能为被销毁,继续运转,但因公许哟啊履行onCreate()从头开始创立Activitiy
- 体系将运用从内存中开释,然后重启。进程和Acitivtiy需求重启,但传递到onCreate()中已保存的实例state bundle对完结使命又必定协助
- 发动时刻介于两者之间,
7、发动耗时
- 冷发动用了 5 秒或更长时刻。
- 温发动用了 2 秒或更长时刻。
- 热发动用了 1.5 秒或更长时刻。
8、体系日志计算
在 Android 4.4(API 等级 19)及更高版别中,logcat 包含一个输出行,其间包含名为 Displayed 的值。此值代表从发动进程到在屏幕上完结对应 Activity 的绘制所用的时刻。
ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms
假如咱们运用异步懒加载的办法,那么 Displayed日志已经打印,可是内容还在加载中。那么异步加载后能够调用activity.reportFullyDrawn()
办法 来让体系打印到调用此办法位置的发动耗时。
9、adb指令计算
adb [-d|-e|-s <serialNumber>] shell am start -S -W
com.example.app/.MainActivity
-c android.intent.category.LAUNCHER
-a android.intent.action.MAIN
发动完结后,将输出:
- ThisTime: 415
- TotalTime: 415 咱们要重视的。
- WaitTime: 437 WaitTime:总的耗时,包含前一个运用Activity pause的时刻和新运用发动的时刻;
ThisTime表明一连串发动Activity的最终一个Activity的发动耗时; TotalTime表明新运用发动的耗时,包含新进程的发动和Activity的发动,但不包含前一个运用Activity pause的耗时。
9、CPU profile java traceview
8.0以下
10、Debug API
除了直接运用 Profifile 发动之外,咱们还能够凭借Debug API生成trace文件。
public class MyApplication extends Application {
public MyApplication() {
Debug.startMethodTracing("enjoy");
}
//.....
}
public class MainActivity extends AppCompatActivity {
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
Debug.stopMethodTracing();
}
//.......
}
运转App,则会在sdcard中生成一个enjoy.trace文件(需求sdcard读写权限)。将手机中的trace文件保存至电 脑,随后拖入Android Studio即可。