Android MultiDex – вопросы о внутренних работах

Недавно я обнаружил новую функциональность MultiDex от Android для работы с приложениями, имеющими более 65 000 ссылок. См. Https://developer.android.com/tools/building/multidex.html.

Может кто-нибудь помочь мне понять следующие вопросы:

1) Как плагин сборки Gradle определяет, что помещать в основной файл dex (classes.dex), а также файлы вторичного dex? Основываясь на документе, есть определенные вещи, которые должны быть в первичном dex, но это не дает никаких примеров. Требуются ли все действия в основном файле dex?

Цитированный текст:

Существуют сложные требования относительно того, какие классы необходимы в основном файле dex при выполнении в среде исполнения Dalvik. Обновления инструмента для сборки Android обрабатывают требования Android, но вполне возможно, что другие включенные библиотеки имеют дополнительные требования к зависимостям, включая использование интроспекции или вызов методов Java из собственного кода. Некоторые библиотеки могут не использоваться, пока средства сборки multidex не будут обновлены, чтобы вы могли указать классы, которые должны быть включены в основной файл dex.

2) При создании только для Android API уровня 21 (Android L) и выше, в плагине Build Gradle существует другое поведение. Он говорит, что он намного быстрее, потому что он «Создает каждый модуль приложения (включая зависимости) в виде отдельных файлов dex. Это обычно называют предварительным расширением». Каково определение модуля в Android? Является ли это библиотекой Java, библиотекой Android и приложениями Android, упомянутой здесь: http://developer.android.com/sdk/installing/studio-build.html#projectModules ? Удаленные или локальные двоичные зависимости (например, Jars) считаются отдельными модулями и, таким образом, попадают в другой файл dex или они включаются в модуль в зависимости от них?

1) Плагин gradle внутренне использует Proguard для создания двух файлов jar в папке сборки intermediates/multi-dex . Один будет основным dex, остальные будут распределены по dex 2, 3 и т. Д.

Задача collect{variant}MultiDexComponents отвечает за создание файла keep for proguard, вы можете видеть этот файл и другие параметры proguard, используемые в подкаталоге варианта, указанного выше. Надеюсь, это будет настраиваться в долгосрочной перспективе.

В настоящее время также имеется ошибка, связанная с тестовыми проектами в 1.0.0-rc1 плагина gradle ( https://code.google.com/p/android/issues/detail?id=80741 ). С некоторыми небольшими изменениями обходной путь, который я опубликовал там, также может быть использован для добавления ваших собственных записей в список удержания (таким образом, чтобы ваши классы попадали в первичный dex) прямо сейчас.

2) Модули относятся к модулям с точки зрения Gradle, но это действительно могут быть разные элементы, упомянутые в списке, к которому вы привязались. Если вы выполняете сборку градиента pre-lollipop из командной строки с помощью --info в качестве флага, вы можете увидеть все файлы dex, передаваемые в dx . (Обратите внимание, что это не должно быть multiidex enabled build или одно с preDexLibraries = false ).

Что помещается в main-dex?

Существуют три последовательные задачи, которые вычисляют, какие классы должны быть упакованы в основной файл dex:

Собрать {вариант} задачу MultiDexComponents

Эта задача записывает имена классов всех компонентов приложения (приложения, действия, службы, получатели, поставщики) в текстовый файл в соответствии с манифестом. То есть, если у вас есть компонент, который не зарегистрирован в манифесте, он не будет помещен в main-dex. И есть другие непроявленные классы – например, аннотации. Чтобы просмотреть полный список, зайдите в задачу CreateManifestKeepList.groovy в источниках плагина.
Результатом этой задачи является файл manifest_keep.txt.

Сжимать {вариант} Задача MultiDexComponents

Эта задача вызывает ProGuard, чтобы создать сжатую банку только с классами, указанными в файле manifest_keep.txt.
Результатом этой задачи является файл componentClasses.jar.

Создать {variant} задачу MainDexClassList

Эта задача принимает файл componentClasses.jar, и для каждого класса вычисляется иерархия прямых ссылок (подробнее см. Реализацию ). То есть, если один из ваших классов компонентов имеет поле типа X, то этот класс X будет добавлен в список main-dex.
Результатом этой задачи является файл maindexlist.txt, который включает список всех классов, которые будут упакованы в основной файл.

Что произойдет, если мой minSdk равен 21?

Ни одна из вышеперечисленных задач не выполняется, если ваша версия minSdk равна 21 – не требуется подсчет списка основных деексов. Это связано с тем, что в ART все файлы dex были преобразованы в один файл .oat во время установки приложения. И поэтому не требуется исправление ClassLoader во время выполнения.