Android Studio直接运行影响启动性能
之前eclipse时代,测试空应用启动性能时,都是直接在IDE中启动,这样修改起来方便。
到了Android Studio时代,这个习惯被我保持下来了。
结果就被Instant Run功能给小小坑了一下。
从性能日志上看,发现空应用在handleBindApplication的时候,在MTK6753芯片上费时60多毫秒,展讯9832芯片上超过100毫秒。
而空应用,既没有Application的onCreate,又没有installProvider之类的,要花这么长时间很奇怪。
后来打印了一下backtrace,原来是这样的:
01-01 01:25:42.280 W/ContextWrapper(12427): at android.content.ContextWrapper.attachBaseContext(ContextWrapper.java:67)
01-01 01:25:42.280 W/ContextWrapper(12427): at com.android.tools.fd.runtime.BootstrapApplication.attachBaseContext(BootstrapApplication.java:244)
01-01 01:25:42.280 W/ContextWrapper(12427): at android.app.Application.attach(Application.java:188)
01-01 01:25:42.280 W/ContextWrapper(12427): at android.app.Instrumentation.newApplication(Instrumentation.java:1021)
01-01 01:25:42.280 W/ContextWrapper(12427): at android.app.Instrumentation.newApplication(Instrumentation.java:1003)
01-01 01:25:42.280 W/ContextWrapper(12427): at android.app.LoadedApk.makeApplication(LoadedApk.java:586)
01-01 01:25:42.280 W/ContextWrapper(12427): at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5054)
01-01 01:25:42.280 W/ContextWrapper(12427): at android.app.ActivityThread.-wrap1(ActivityThread.java)
01-01 01:25:42.280 W/ContextWrapper(12427): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1564)
01-01 01:25:42.280 W/ContextWrapper(12427): at android.os.Handler.dispatchMessage(Handler.java:111)
01-01 01:25:42.280 W/ContextWrapper(12427): at android.os.Looper.loop(Looper.java:205)
01-01 01:25:42.280 W/ContextWrapper(12427): at android.app.ActivityThread.main(ActivityThread.java:5865)
01-01 01:25:42.280 W/ContextWrapper(12427): at java.lang.reflect.Method.invoke(Native Method)
01-01 01:25:42.280 W/ContextWrapper(12427): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844)
01-01 01:25:42.280 W/ContextWrapper(12427): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:734)
原来InstantRun的时候,安装的应用的Application是com.android.tools.fd.runtime.BootstrapApplication,这个Application重载了attachBaseContext,正是这个重载的方法耗费了这么长的时间。
Application的attach方法是个hide的方法:
183 /**
184 * @hide
185 */
186 /* package */ final void attach(Context context) {
187 attachBaseContext(context);
188 mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
189 }
```
attach会调用到当前Application的attachBaseContext,正常的attachBaseContext方法是这样的:
比如ContextThemeWrapper的attachBaseContext,就是对基类的调用:
50 @Override
51 protected void attachBaseContext(Context newBase) {
52 super.attachBaseContext(newBase);
53 }
而ContextWrapper的attachBaseContext是这样的:
65 protected void attachBaseContext(Context base) {
66 if (mBase != null) {
67 throw new IllegalStateException("Base context already set");
68 }
69 mBase = base;
70 }
所以,没有重载的普通类,在attachBaseContext这一步几乎不花时间。
## 解决方案