Android 微技巧之配置多 Dex 處理

為方法數(shù)超過(guò) 64K 的應(yīng)用啟用多 dex 文件

當(dāng)您的應(yīng)用及其引用的庫(kù)超過(guò) 65536 個(gè)方法時(shí)采章,您會(huì)遇到一個(gè)編譯錯(cuò)誤弧蝇,指明您的應(yīng)用已達(dá)到 Android 編譯架構(gòu)規(guī)定的引用限制:

trouble writing output:
Too many field references: 131000; max is 65536.
You may try using --multi-dex option.

較低版本的編譯系統(tǒng)會(huì)報(bào)告一個(gè)不同的錯(cuò)誤蝶涩,但指示的是同一個(gè)問(wèn)題:

Conversion to Dalvik format failed:
Unable to execute dex: method ID not in [0, 0xffff]: 65536

這種錯(cuò)誤情況都會(huì)顯示一個(gè)共同的數(shù)字:65536骤铃。此數(shù)字表示單個(gè) Dalvik Executable(DEX)字節(jié)碼文件內(nèi)的代碼可調(diào)用的引用總數(shù)沛善。該文章主要介紹如何通過(guò)啟用稱為“多 DEX 文件”的應(yīng)用配置(該配置使您的應(yīng)用能夠編譯和讀取多個(gè) DEX 文件)來(lái)越過(guò)這一限制。

關(guān)于 64K 引用限制

Android 應(yīng)用(APK)文件包含 Dalvik Executable(DEX)文件形式的可執(zhí)行字節(jié)碼文件驶乾,這些文件包含用來(lái)運(yùn)行您的應(yīng)用的已編譯代碼邑飒。Dalvik Executable 規(guī)范將可在單個(gè) DEX 文件內(nèi)引用的方法總數(shù)限制為 65536,其中包括 Android 框架方法级乐、庫(kù)方法以及您自己代碼中的方法疙咸。由于 65536 等于 64 * 1024,因此這一限制成為“64K 引用限制”风科。

Android 5.0 之前版本的多 dex 文件支持

Android 5.0(API Level 21)之前的平臺(tái)版本使用 Dalvik 運(yùn)行時(shí)來(lái)執(zhí)行應(yīng)用代碼撒轮。默認(rèn)情況下,Dalvik 將應(yīng)用限制為每個(gè) APK 只能使用一個(gè) classes.dex 字節(jié)碼文件贼穆。要繞過(guò)這一限制题山,您可以在您的項(xiàng)目中添加多 dex 文件支持庫(kù):

 dependencies {
    implementation 'androidx.multidex:multidex:2.0.1'
}

如果您不使用 AndroidX,請(qǐng)改為添加以下支持庫(kù)依賴項(xiàng):

dependencies {
  implementation 'com.android.support:multidex:1.0.3'
}

此庫(kù)會(huì)成為應(yīng)用的主要 DEX 文件的一部分故痊,然后管理對(duì)其他 DEX 文件及其包含的代碼訪問(wèn)顶瞳。如需了解詳情,請(qǐng)參與下面有關(guān)下面介紹針對(duì)多 dex 文件配置您的應(yīng)用的部分愕秫。

  • 注意:如果為您的項(xiàng)目配置的多 dex 文件使用的是 minSdkVersion 20 或更低版本慨菱,而您將其部署到運(yùn)行 Android 4.4(API Level 20)或更低版本系統(tǒng)的目標(biāo)設(shè)備上,則 Android Studio 會(huì)停用 Instant Run戴甩。
Android 5.0 及更高版本的多 dex 文件支持

Android 5.0(API 級(jí)別 21)及更高版本使用名為 ART 的運(yùn)行時(shí)符喝,它本身支持從 APK 文件加載多個(gè) DEX 文件。ART 在應(yīng)用安裝時(shí)執(zhí)行預(yù)編譯甜孤,掃描 classesN.dex 文件协饲,并將它們編譯成單個(gè) .oat 文件,以供 Android 設(shè)備執(zhí)行课蔬。因此囱稽,如果您的 minSdkVersion 為 21 或更高的值,則不需要多 dex 文件支持庫(kù)二跋。

  • 注意:使用 Instant Run 時(shí)战惊,如果將應(yīng)用的 minSdkVersion 設(shè)為 21 或更高的值,Android Studio 會(huì)自動(dòng)針對(duì)多 dex 文件配置您的應(yīng)用扎即。由于 Instant Run 僅適用于調(diào)試版本的應(yīng)用吞获,因此您仍然需要針對(duì)多個(gè) dex 文件配置發(fā)布版本,以規(guī)避 64K 限制谚鄙。
規(guī)避 64K 限制

在將您的應(yīng)用配置為支持使用 64K 或更多方法引用之前各拷,您應(yīng)該采取措施來(lái)減少應(yīng)用代碼調(diào)用的引用總數(shù),包括由您的應(yīng)用代碼或包含的庫(kù)定義的方法闷营。以下策略可幫助您避免達(dá)到 DEX 引用限制:

  • 檢查應(yīng)用的直接和傳遞依懶性 - 確保您在應(yīng)用中使用任何龐大依賴庫(kù)所帶來(lái)的好處多于為應(yīng)用添加大量代碼所帶來(lái)的弊端烤黍。一種常見(jiàn)的反面模式是知市,僅僅為了使用幾個(gè)實(shí)用方法就在應(yīng)用中加入非常龐大的庫(kù)。減少您的應(yīng)用代碼依賴項(xiàng)往往能夠幫助您規(guī)避 DEX 引用限制速蕊。

  • 通過(guò) ProGuard 移除未使用的代碼 - 啟用代碼壓縮嫂丙,以便對(duì)您的發(fā)布版本運(yùn)行 ProGuard。啟用代碼壓縮规哲,以便對(duì)您的發(fā)布版本運(yùn)行 ProGuard跟啤。啟用壓縮可確保您交付的 APK 不含有未使用的代碼。

使用這些技巧使您不必在應(yīng)用中應(yīng)用多 dex 文件唉锌,同時(shí)還會(huì)減少 APK 的總大小隅肥。

針對(duì)多 dex 文件配置您的應(yīng)用

將您的應(yīng)用項(xiàng)目設(shè)為使用多 dex 文件配置要求您對(duì)應(yīng)用項(xiàng)目進(jìn)行以下修改,具體取決于應(yīng)用支持最低 Android 版本袄简。如果您的 minSdkVersion 設(shè)為 21 或更高的值腥放,您只需要在模塊級(jí) build.gradle 文件中將 multiDexEnabled 設(shè)為 true,如下所示:

 android {
    defaultConfig {
        ...
        minSdkVersion 21
        targetSdkVersion 28
        multiDexEnabled true
    }
    ...
}

不過(guò)绿语,如果您的 minSdkVersion 設(shè)為 20 或更低的值捉片,則必須使用多 dex 文件支持庫(kù),具體操作步驟如下:

  1. 修改模塊機(jī) build.gradle 文件以啟用多 dex 文件汞舱,并將多 dex 文件庫(kù)添加為依賴項(xiàng),如下所示:
android {
    defaultConfig {
        ...
        minSdkVersion 15
        targetSdkVersion 28
        multiDexEnabled true
    }
    ...
}

dependencies {
  compile 'com.android.support:multidex:1.0.3'
}
  1. 根據(jù)是否替換 Application 類宗雇,執(zhí)行以下某項(xiàng)操作:
  • 如果您不替換 Application 類昂芜,請(qǐng)修改清單以設(shè)置 <application> 標(biāo)記中 android:name,如下所示:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.myapp">
        <application
                android:name="android.support.multidex.MultiDexApplication" >
            ...
        </application>
    </manifest>
    
  • 如果您替換 Application 類赔蒲,請(qǐng)對(duì)其進(jìn)行更改以擴(kuò)展 MultiDexApplication(如果可能)泌神,如下所示:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.myapp">
        <application
                android:name="android.support.multidex.MultiDexApplication" >
            ...
        </application>
    </manifest>
    
  • 或者,如果您替換 Application類舞虱,但無(wú)法更改基類欢际,則可以改為替換 attachBaseContext()方法并調(diào)用 MultiDex.install(this)來(lái)啟用多 dex 文件:

public class MyApplication extends SomeOtherApplication {
  @Override
  protected void attachBaseContext(Context base) {
     super.attachBaseContext(base);
     MultiDex.install(this);
  }
}
  • 注意:在 MultiDex.install() 完成之前,不要通過(guò)反射或 JNI 執(zhí)行 MultiDex.install() 或其他任何代碼矾兜。多 dex 文件跟蹤功能不會(huì)追蹤這些調(diào)用损趋,從而導(dǎo)致出現(xiàn) ClassNotFoundException,或因 DEX 文件之間的類分區(qū)錯(cuò)誤而導(dǎo)致驗(yàn)證錯(cuò)誤椅寺。

現(xiàn)在浑槽,當(dāng)您編譯應(yīng)用時(shí),Android 編譯工具會(huì)根據(jù)需要構(gòu)造主要 DEX 文件(classes.dex)和 輔助 DEX 文件(classes2.dex 和 classes3.dex 等)返帕。然后桐玻,編譯系統(tǒng)會(huì)將所有 DEX 文件打包到您的 APK 中。

在運(yùn)行時(shí)荆萤,多 dex 文件 API 使用特殊的類加載器來(lái)搜索適用于您的方法的所有 DEX 文件(而不是只在主 classes.dex 文件中搜索)镊靴。

多 dex 文件支持庫(kù)的局限性

多 dex 文件支持庫(kù)具有一些已知的局限性,將其納入您的以你雇傭編譯配置時(shí),您應(yīng)注意這些局限性并進(jìn)行針對(duì)的測(cè)試:

  • 啟動(dòng)期間在設(shè)備的數(shù)據(jù)分區(qū)上安裝 DEX 文件的過(guò)程相當(dāng)復(fù)雜偏竟,如果輔助 DEX 文件較大煮落,可能會(huì)導(dǎo)致應(yīng)用無(wú)響應(yīng)(ANR)錯(cuò)誤。在這種情況下苫耸,您應(yīng)通過(guò) ProGuard 應(yīng)用代碼壓縮州邢,以盡量減小 DEX 文件的大小,并移除未使用的那部分代碼褪子。

  • 當(dāng)運(yùn)行的版本低于 Android 5.0(API Level 21)時(shí)量淌,使用多 dex 文件不足以避開(kāi) linearalloc 限制(問(wèn)題 78035)。此上線在 Android 4.0(API 級(jí)別 14)中有所提高嫌褪,但這并不未完全解決該問(wèn)題呀枢。在低于 Android 4.0 的版本中,您可能會(huì)在達(dá)到 DEX 索引限制之前達(dá)到 linearalloc 限制笼痛。因此裙秋,如果您的目標(biāo) API 級(jí)別低于 14,請(qǐng)?jiān)谶@些版本的平臺(tái)上進(jìn)行全面測(cè)試缨伊,因?yàn)槟膽?yīng)用可能會(huì)在啟動(dòng)時(shí)或加載特定類組時(shí)出現(xiàn)問(wèn)題摘刑。

代碼壓縮課件較少甚至有可能消除這些問(wèn)題。

聲明主要 DEX 文件中必需的類

為多 dex 文件應(yīng)用編譯每個(gè) DEX 文件時(shí)刻坊,編譯工具會(huì)執(zhí)行復(fù)雜的決策制定來(lái)確定主要 DEX 文件中需要的類枷恕,以便應(yīng)用能夠成功啟動(dòng)。如果主要 DEX 文件中未提供啟動(dòng)期間需要的任何類谭胚,則應(yīng)用會(huì)崩潰并出現(xiàn) java.lang.NoClassDefFoundError 錯(cuò)誤徐块。

對(duì)于直接從您的應(yīng)用代碼訪問(wèn)代碼,不應(yīng)發(fā)生這種情況灾而,因?yàn)榫幾g工具可以識(shí)別這些代碼路徑胡控。但是,當(dāng)代碼路徑的可見(jiàn)性較低時(shí)(例如旁趟,當(dāng)您使用的庫(kù)具有復(fù)雜的依賴項(xiàng)時(shí))昼激,可能會(huì)發(fā)生這種情況。例如轻庆,如果代碼使用自檢機(jī)制或從原生代碼調(diào)用 Java 方法癣猾,那么可能不會(huì)將這些類識(shí)別為主要 DEX 文件中必需類纬向。

因此吼鱼,如果您收到 java.lang.NoClassDefFoundError雁仲,則必須使用版本類型中的 multiDexKeepFilemultiDexKeepProguard 屬性聲明這些其他類遏考。
以手動(dòng)將這些類指定為主要 DEX 文件中的必需類壶笼。如果某個(gè)類在 multiDexKeepFile 或 multiDexKeepProguard 文件中匹配到暖释,則會(huì)將該類添加到主要 DEX 文件坏瞄。

multiDexKeepFile 屬性

您在 multiDexKeepFile 中指定的文件應(yīng)該每行包含一個(gè)類扬跋,并且采用 com/example/MyClass.class 格式。例如拓春,您可以創(chuàng)建一個(gè)名為 multidex-config.txt 的文件释簿,如下所示:

com/example/MyClass.class
com/example/MyOtherClass.class

然后,您可以針對(duì)版本類型聲明該文件硼莽,如下所示:

android {
    buildTypes {
        release {
            multiDexKeepFile file('multidex-config.txt')
            ...
        }
    }
}

請(qǐng)注意庶溶,Gradle 會(huì)讀取相對(duì)于 build.gradle 文件路徑,因此如果 multidex-config.txt 與 build.gradle 文件在同一目錄中懂鸵,以上示例將有效偏螺。

multiDexKeepProguard 屬性

multiDexKeepProguard 文件使用與 Proguard 相同格式,并且支持全部 Progurad 語(yǔ)法匆光。如需詳細(xì)了解 Proguard 格式和語(yǔ)法套像,請(qǐng)參閱 Proguard 手冊(cè)中的 Keep 選項(xiàng)一節(jié)。

您在 multiDexKeepProjuard 中指定的文件應(yīng)該在任何有效的 ProGuard 語(yǔ)法中包含 -keep 選項(xiàng)终息。例如夺巩,-keep com.example.MyClass.class。您可以創(chuàng)建一個(gè)名為 multidex-config.pro 的文件周崭,如下所示:

-keep class com.example.MyClass
-keep class com.example.MyClassToo

如果您要指定軟件包中的所有類柳譬,文件將如下所示:

-keep class com.example.** { *; } // All classes in the com.example package

然后,您可以針對(duì)版本類型聲明該文件续镇,如下所示:

android {
    buildTypes {
        release {
            multiDexKeepProguard file('multidex-config.pro')
            ...
        }
    }
}
在開(kāi)發(fā)編譯中優(yōu)化多 dex 文件

多 dex 文件配置會(huì)大幅增加編譯時(shí)間征绎,因?yàn)榫幾g系統(tǒng)必須就那些類必須包含在主要 DEX 文件中以及哪些類可以包含在輔助 DEX 文件中做出復(fù)雜的決策。這意味著磨取,使用多 dex 文件的增量編譯通常耗時(shí)較長(zhǎng),可能會(huì)拖慢您的開(kāi)發(fā)進(jìn)度柴墩。

要縮短較長(zhǎng)的增量編譯時(shí)間忙厌,您應(yīng)使用 dex 預(yù)處理在編譯之間重用多 dex 文件輸出。dex 預(yù)處理依賴于一種只在 Android 5.0(API 級(jí)別 21)及更高版本中提供的 ART 格式江咳。如果您使用的是 Android Studio 2.3 及更高版本逢净,那么在將您的應(yīng)用部署到搭載 Android 5.0(API 級(jí)別 21)或更高版本的設(shè)備上時(shí),IDE 會(huì)自動(dòng)使用此功能歼指。

  • 提示:Android Pluging for gradle 3.0.0 及更高版本得到進(jìn)一步改進(jìn)來(lái)優(yōu)化編譯速度爹土,如每個(gè)類的 dex 處理(這樣,只有您修改的類會(huì)重新進(jìn)行 dex 處理)踩身。一般來(lái)說(shuō)胀茵,為了獲得最佳開(kāi)發(fā)體驗(yàn),您應(yīng)該使用升級(jí)最新版 Android Studio 和 Android 插件挟阻。

不過(guò)琼娘,如果您是從命令行運(yùn)行 Gradle 編譯峭弟,則需要將 minSdkVersion 設(shè)為 21 或更高值以啟用 dex 預(yù)處理。要保留正式版的設(shè)置脱拼,一種有用的策略是使用產(chǎn)品類型(一個(gè)開(kāi)發(fā)類型和一個(gè)發(fā)布類型瞒瘸,它們具有不同的 minSdkVersion 值)來(lái)創(chuàng)建兩個(gè)應(yīng)用版本,如下所示熄浓。

android {
    defaultConfig {
        ...
        multiDexEnabled true
        // The default minimum API level you want to support.
        minSdkVersion 15
    }
    productFlavors {
        // Includes settings you want to keep only while developing your app.
        dev {
            // Enables pre-dexing for command line builds. When using
            // Android Studio 2.3 or higher, the IDE enables pre-dexing
            // when deploying your app to a device running Android 5.0
            // (API level 21) or higher—regardless of what you set for
            // minSdkVersion.
            minSdkVersion 21
        }
        prod {
            // If you've configured the defaultConfig block for the production version of
            // your app, you can leave this block empty and Gradle uses configurations in
            // the defaultConfig block instead. You still need to include this flavor.
            // Otherwise, all variants use the "dev" flavor configurations.
        }
    }
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                                                 'proguard-rules.pro'
        }
    }
}
dependencies {
    compile 'com.android.support:multidex:1.0.3'
}

要了解有助于改進(jìn)編譯速度(從 Android Studio 或命令行中)的更多策略情臭,請(qǐng)閱讀優(yōu)化您的編譯速度。如需詳細(xì)了解如何使用編譯變體赌蔑,請(qǐng)參閱配置編譯變體俯在。

  • 提示:由于您有滿足不同多 dex 文件需求的不同編譯變體,因此也可以為不同的變體提供不同的清單文件(這樣惯雳,只有適用于 API 級(jí)別 20 及更低級(jí)別的清單文件會(huì)更改 <application> 標(biāo)記名稱)朝巫,或者為每個(gè)變體創(chuàng)建不同的 Application 子類(這樣,只有適用于 API 級(jí)別 20 及更低級(jí)別的子類會(huì)擴(kuò)展 MultiDexApplication 類或調(diào)用 MultiDex.install(this)
測(cè)試多 dex 文件應(yīng)用

編寫(xiě)多 dex 文件應(yīng)用的插樁測(cè)試時(shí)石景,如果使用 MonitoringInstrumentation(或 AndroidJUnitRunner)插樁測(cè)試劈猿,則不需要額外的配置。如果使用其他 Instrumentation潮孽,則必須將其 onCreate() 方法替換為以下代碼:

public void onCreate(Bundle arguments) {
  MultiDex.install(getTargetContext());
  super.onCreate(arguments);
  ...
}

注意

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末仗颈,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子椎例,更是在濱河造成了極大的恐慌挨决,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件订歪,死亡現(xiàn)場(chǎng)離奇詭異脖祈,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)刷晋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門盖高,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人眼虱,你說(shuō)我怎么就攤上這事喻奥。” “怎么了捏悬?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵撞蚕,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我过牙,道長(zhǎng)诈豌,這世上最難降的妖魔是什么仆救? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮矫渔,結(jié)果婚禮上彤蔽,老公的妹妹穿的比我還像新娘。我一直安慰自己庙洼,他們只是感情好顿痪,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著油够,像睡著了一般蚁袭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上石咬,一...
    開(kāi)封第一講書(shū)人閱讀 49,764評(píng)論 1 290
  • 那天揩悄,我揣著相機(jī)與錄音,去河邊找鬼鬼悠。 笑死删性,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的焕窝。 我是一名探鬼主播蹬挺,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼它掂!你這毒婦竟也來(lái)了巴帮?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤虐秋,失蹤者是張志新(化名)和其女友劉穎榕茧,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體客给,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡雪猪,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了起愈。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡译仗,死狀恐怖抬虽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情纵菌,我是刑警寧澤阐污,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站咱圆,受9級(jí)特大地震影響笛辟,放射性物質(zhì)發(fā)生泄漏功氨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一手幢、第九天 我趴在偏房一處隱蔽的房頂上張望捷凄。 院中可真熱鬧,春花似錦围来、人聲如沸跺涤。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)桶错。三九已至,卻和暖如春胀蛮,著一層夾襖步出監(jiān)牢的瞬間院刁,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工粪狼, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留退腥,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓鸳玩,卻偏偏與公主長(zhǎng)得像阅虫,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子不跟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容