Android5.0以下のMultiDexで起動するシルクのように滑らか

5843 ワード

MultiDexの公式ソリューションの使用
  • minSdkVersion >=21:multiDexEnabled trueを追加するだけでOK、その他はでたらめをしなくてもいい
    android {
        defaultConfig {
            ...
            minSdkVersion 21 
            targetSdkVersion 26
            multiDexEnabled true //           ,     
        }
        ...
    }
    
  • minSdkVersion <21:それはちょっと面倒です.
  • 上記第1条のように、multiDexEnabled true
  • を加える.
  • compile 'com.android.support:multidex:1.0.1'
  • MultiDexApplicationを使用するか、カスタムapplicationMultidex.install(this);を次のように追加する
    public class MyApplication extends SomeOtherApplication {
        @Override
        protected void attachBaseContext(Context base) {
            super.attachBaseContext(context);
            Multidex.install(this);
        }
    }
    
  • .
    minSdkVersion<21の場合に遭遇したピット
  • Android5.0以上の設備はまだしも、Multidex.install(this);はそれほど時間を取らず、基本的には秒で実行されている.Android5.0以上の設備はapkを設置する際にMultidexを最適化しているので、初めて開いたときに実行すると、Multidex.install(this);
  • を占有することはない.
  • しかしAndroid5.0以下の設備の下で、Multidex.install(this);は数秒の時間(私のプログラムでは4秒ほどかかりました)を費やして、ソフトウェアが初めて開いて少なくとも白いスクリーンが4秒でトップページに入ることを意味します(まず靴を置いて、もちろん解決策があって、後ろにあります)
  • 性能の弱い携帯電話では、Multidex.install(this);が実行する時間が長く、ANR(結局、メインスレッドでこんなに長い時間実行されている)の
  • が発生する確率があります.
    ぶんせき
  • は、Android5.0以下の装置においてMultidex.install(this)が実行するに違いない.そうでなければ、主Dex以外のDexファイル
  • をロードすることはできない.
  • メインスレッドで実行するとARNが現れる以上、新しいプロセスで初期化しましょう.

  • 解決する
  • MyApplication.class
    override fun attachBaseContext(base: Context?) {
        super.attachBaseContext(base)
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP && TextUtils.equals(applicationContext?.packageName, processName)) {
            val multiDexPreference = getSharedPreferences("MultiDexPreference", Context.MODE_PRIVATE)
            if (multiDexPreference.getString(BuildConfig.VERSION_NAME, "") != the2thDexSHA1) {//     multiDex
                val lock = java.lang.Object()
                thread {
                    Looper.prepare()
                    val handler = object : Handler(Looper.myLooper()) {
                        override fun handleMessage(msg: Message?) {
                            super.handleMessage(msg)
                            synchronized(lock) {
                                lock.notify()
                                multiDexPreference.edit().putString(BuildConfig.VERSION_NAME, the2thDexSHA1).apply()
                                if (null != Looper.myLooper()) Looper.myLooper().quit()
                            }
                        }
                    }
                    startService( //        multiDex
                            Intent(applicationContext, MultiDexService::class.java)
                                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                                    .putExtra("MESSENGER", Messenger(handler))
                    )
                    Looper.loop()
                }
                synchronized(lock) {
                    try {
                        lock.wait(30000)
                    } catch (e: InterruptedException) {
                        e.printStackTrace()
                    }
                }
            }
        }
        if (!processName.endsWith("multiDex")) {
            //   Android5.0     ,                 MultiDex ,            
            MultiDex.install(this)
        }
    }
    
    private val the2thDexSHA1: String? by lazy {
        val ai = applicationInfo
        val source = ai?.sourceDir
        try {
            val jar = JarFile(source)
            val mf = jar.manifest
            val map = mf.entries
            val a = map["classes2.dex"]
            a?.getValue("SHA1-Digest").toString()
        } catch (e: Exception) {
            e.printStackTrace()
        }
        null
    }
    
  • MultiDexService.class
    class MultiDexService : IntentService("MultiDexService") {
        override fun onHandleIntent(intent: Intent?) {
            val messenger: Messenger? = intent?.getParcelableExtra("MESSENGER")
            MultiDex.install(application)
            messenger?.send(Message())
            android.os.Process.killProcess(android.os.Process.myPid())
    
        }
    }
    
  • AndroidManifest.xml
    
    

  • 小さな結び目
  • これでローエンド機のARNは回避され、少なくとも死なない...

  • 新しいピット&分析
  • しかし、ソフトウェアが開いた後も長い間白い画面/黒い画面があり、少しも滑らかではありません.
  • この穴は簡単で、LaunchActivitythemeを設置すればよい、windowBackgroundのデフォルト壁紙
  • を設置すればよい.
    絹のような滑らかなソリューション
  • style
    
    
  • drawable/splash_placeholder
    
    
        
        
            
        
    
    
  • AndroidManifest.xml,修正theme次の例
    
            
                
                
            
    
    
  • 小結
    これで糸のようになめらかになる
    リファレンス
    Androidの性能の最適化の方面はすべてここにあります@鴻洋Android MultiDexは初めてアプリを起動して最適化します実はあなたはMultiDexがいったいどれだけ穴があることを知りません