1. 程式人生 > 其它 >Flutter APP在模擬機除錯提示MultiDex超過64K的問題的解決方案

Flutter APP在模擬機除錯提示MultiDex超過64K的問題的解決方案

參考網路方案可以解決:

App啟用MultiDex功能

於 2018-08-31 16:03:37 釋出213 收藏 分類專欄: 用法概括 文章標籤: MultiDex 效能調優  65535   用法概括專欄收錄該內容 116 篇文章1 訂閱 訂閱專欄

轉自:http://kaedea.com/2015/09/02/android/enable-multidex/

App 啟動 MultiDex 主要是為了解決 “65535 方法數超標” 以及 “INSTALL_FAILED_DEXOPT” 問題,就目前來說,對於使用 Android Studio 的朋友來說,MultiDex 這個術語應該不陌生。而對於那些從早期使用 

Eclipse 開發 Android 的人來說,這個詞語則更加再熟悉不過了,因為用 Eclipse 開啟 MultiDex 功能實在是太坑爹了(默默給 Eclipse 加一把土)。

出現的問題

65535 問題

當 App 的功能越來越豐富、使用的庫越來越多時,其包含的 Java 方法總數也越來越多,這時候就會出現 65535 問題。

在構建 apk 的時候限制了一個 dex 檔案能包含的方法數,其總數不能超過 65535(則 64K,1K = 2^10 = 1024 , 64 * 1024 = 65535)。MultiDex, 顧名思義,是指多 dex 實現,大多數 App,解壓其 apk 後,一般只有一個 classes.dex 檔案,採用 MultiDex 的 App 解壓後可以看到有 classes.dex,classes2.dex,… classes(N).dex,這樣每個 dex 都可以最大承載 64k 個方法,很大限度地緩解了單 dex 方法數限制。

(2016-10-1 具體原因分析可以參考由 Android-65K 方法數限制引發的思考

LinearAlloc 問題

現在這個問題已經不常見了,它多發生在 2.x 版本的裝置上,安裝時會提示 INSTALL_FAILED_DEXOPT。這個問題發生在安裝期間,在使用 Dalvik 虛擬機器的裝置上安裝 APK 時,會通過 DexOpt 工具將 Dex 檔案優化為 odex 檔案,即 Optimized Dex,這樣可以提高執行效率 (不同的裝置需要不同的 odex 格式,所以這個過程只能安裝 apk 後進行)。

LinearAlloc 是一個固定大小的緩衝區,dexopt 使用 LinearAlloc 來儲存應用的方法資訊,在 Android 的不同版本中有 4M/5M/8M/16M 等不同大小,目前主流 4.x 系統上都已到 8MB 或 16MB,但是在 Gingerbread 或以下系統(2.2 和 2.3)LinearAlloc 分配空間只有 5M 大小的。當應用的方法資訊過多導致超出緩衝區大小時,會造成 dexopt 崩潰,造成 INSTALL_FAILED_DEXOPT 錯誤。

啟用 MultiDex 解決問題

直接忽視 Eclipse,在 Android Studio 中,可以通過以下方式來啟用 MultiDex。

環境要求

  • 使用 Android Studio 開發工具;
  • Android SDK Build Tools >= 21.1;
  • 使用 Support Repository 中的 multidex (剛出來時是 0.1 版本,目前已有有 1.0.0 和 1.0.1);

配置 build.gradle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
android {
    compileSdkVersion 21
    buildToolsVersion "21.1.0"

    defaultConfig {
        ...
        minSdkVersion 14
        targetSdkVersion 21
        ...

        multiDexEnabled true // Enable MultiDex.
    }
    ...
}

dependencies {
  compile 'com.android.support:multidex:1.0.1'
}

在程式碼裡啟動 MultiDex

最後,在 Java 程式碼裡啟動 MultiDex,有兩種方式可以搞定。

方式一,使用 MultiDexApplication。

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="xxx">
    <application
        ...
        android:name="android.support.multidex.MultiDexApplication">
        ...
    </application>
</manifest>

方式二,在自己的 Application#attachBaseContext(Context) 方法裡新增以下程式碼。

1
2
3
4
5
6
public class MyApplication extends Application {
	protected void attachBaseContext(Context base) {
		super.attachBaseContext(base);
		MultiDex.install(this); // Enable MultiDex.
	}
}

存在的問題

MultiDex 並不是萬全的方案,Google 貌似不太熱衷於舊版本的相容工作,通過閱讀 MultiDex Support 庫的原始碼,我們也能發現其程式碼寫得貌似沒有那麼嚴謹。

目前來說,使用 MultiDex 可能存在以下問題。

NoClassDefFoundError

如果你在呼叫 MultiDex#install(Context) 做了別的工作,而這些工作需要用到的類卻存在於別的 dex 檔案裡面(Secondary Dexes),就會出現類找不到的執行時異常。

正確的做法是把這些需要用到的類標記在 multidex.keep 清單檔案裡面,再在 build.gradle 裡面啟用該清單檔案。

1
2
3
4
5
6
7
8
9
10
11
android {

  defaultConfig {
    multiDexEnabled true
    multiDexKeepProguard file('multidex.pro')
   }
}

dependencies {
  compile'com.android.support:multidex:1.0.1'
}

multiDexKeepProguard使用的是類似於混淆檔案的過濾規則,出了這個配置項之外還有multiDexKeepFile,這個要求你在清單檔案裡把所有的類都羅列出來。

卡頓問題

通過閱讀原始碼,我們可以看出,目前 Android 5.0 以上的裝置已經自身支援了 MultiDex 功能,也就是說在安裝 apk 的時候,系統已經會幫我們把 apk 裡面的所有 dex 檔案都做好 Optimize 處理,所以不需要我們在程式碼裡啟用 MultiDex 了。但是對於 Android 5.0 以下的設定,則依然要求我們啟用 MultiDex。而這些系統的裝置在第一次執行 App 的時候,需要對所有的 Secondary Dexes 檔案都進行一次解壓以及 Optimize 處理(生成 odex 檔案),這段時間會有明顯的耗時(大概 5000 毫秒左右,dex 越多越大越明顯),所有會產生明顯的卡頓現象。

不過好在,在 Application#attachBaseContext(Context) 中,UI 執行緒的阻塞是不會引發 ANR 的,只不過這段長時間的卡頓(白屏)還是會影響使用者體驗,解決方案能想到的有兩種。

第一種,在安裝一個新的 apk 的時候,先在 Worker 執行緒裡做好 MultiDex 的 Optimize 工作,安裝 apk 並啟動後,直接使用之前 Optimize 產生的 odex 檔案,這樣就可以避免第一次啟動時候的 Optimize 工作。

第二種,啟動 App 的時候,先顯示一個簡單的 Splash 閃屏介面,然後啟動 Worker 執行緒執行 MultiDex#install(Context) 工作,就可以避免 UI 執行緒阻塞。不過要確保啟動以及啟動 MultiDex#install(Context) 所需要的類都在 Main Dex 裡面。

多程序同步

參考 Google 的 MultiDex 的原始碼,可以發現 Google 並沒有考慮多程序同步的問題,如果 App 是多程序的,並且剛好同時有兩個程序出發了 MultiDex#install(Context) 工作,可以會有多程序衝突的風險。

如果你採用了上面解決卡頓問題時說到的第二種方法,你也應該考慮多程序的問題,因為這種方法並不是在程序一啟動就在主執行緒裡面去做 MultiDex 初始化了,可能存在同步問題的風險。

其他問題

早期在使用 MultiDex 的時候,Android Studio 會出現 apk 編譯後無法安裝的問題,然而使用命令列編譯出來的 apk 檔案又可以安裝了,這個問題現在基本沒有出現了,不再追究原因了。

參考資料:

# 效能調優 # MultiDex