1、发动图

性能优化(四)-Android启动优化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的耗时。

性能优化(四)-Android启动优化1

9、CPU profile java traceview

8.0以下

性能优化(四)-Android启动优化1

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即可。