Multidex(一)之源码解析中分析过MultiDex第一次加载出现ANR的原因是因为**提取Dex以及DexOpt这两个过程都是耗时的操作,而且他们还都发生在主进程。**稍等:主进程,ANR,脑袋里好像闪现一道灵光,**既然在主进程执行会产生ANR,那能不能换个进程执行呢?**橘生淮南则为橘,生于淮北则为枳;换个进程说不定就有突破点。说干就干,凭借程序员机智的大脑,分毫之间,一个优化方案的雏形已经了然于胸:App第一次启动时单独开一个额外优化的进程率先进行Dex提取以及DexOpt的操作,与此同时主进程在后台等待,优化的进程执行完毕之后通知主进程继续往下执行,主进程在执行MultiDex.install时发现已经是提前优化好了Dex,直接执行,非常快,毫秒级别,不会造成卡顿,愉快的往下继续执行。
-----------![](https://img-blog.csdnimg.cn/img_convert/93a33d950057371ec8ab17557855af6e.png)
在Application的attachBaseContext中执行优化方案;
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
//只有主进程以及SDK版本5.0以下才走。
if (isMainProcess(Application.this) && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
if (!dexOptDone(base)) {
preLoadDex(base);
}
long startTime = System.currentTimeMillis();
MultiDex.install(this);
LogUtil.i(TAG,“MainProcessCostTime:”+(System.currentTimeMillis() - startTime));
}
}
/**
-
当前版本是否进行过DexOpt操作。
-
@param context
-
@return
*/
private boolean dexOptDone(Context context) {
SharedPreferences sp = context.getSharedPreferences(
DeviceUtil.getVersionName(context), MODE_MULTI_PROCESS);
return sp.getBoolean(“dexoptdone”, false);
}
/**
-
在单独进程中提前进行DexOpt的优化操作;主进程进入等待状态。
-
@param base
*/
public void preLoadDex(Context base) {
Intent intent = new Intent(Application.this, PreLoadDexActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
base.startActivity(intent);
while (!dexOptDone(base)) {
try {
//主线程开始等待;直到优化进程完成了DexOpt操作。
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
然后在PreLoadDexActivity中执行优化的操作,完成后修改标示;
@Override
public void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
overridePendingTransition(0, 0);//取消掉系统默认的动画。
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.predexlayout);
new Thread() {
@Override
public void run() {
super.run();
try {
long time = System.currentTimeMillis();
MultiDex.install(getApplication());
LogUtil.i(“lz”, “PreLoadDexActivityCostTime:” + (System.currentTimeMillis() - time));
= System.currentTimeMillis();
MultiDex.install(getApplication());
LogUtil.i(“lz”, “PreLoadDexActivityCostTime:” + (System.currentTimeMillis() - time));