Site icon AppTractor

Обессахаривание Android по-простому

Представьте, что вам нужно использовать LocalDate.now() для вашего приложения. Если вам нужно поддерживать более старую версию Android с SDK до 26, то код по умолчанию у вас не будет работать.

Если вы послушаете свой компилятор, то он предупредит вас, что вызов требует уровня API 26:

Call requires API level 26 (current min is 12): java.time.LocalDate#now

Обессахаривание Android по-простому

Чтобы решить эту проблему, нам нужно сделать то, что называется Desugaring (обессахаривание). Вкратце, это добавление некоторых дополнительных настроек в build.gradle вашего модуля приложения:

android {
    defaultConfig {
        // Required when setting minSdkVersion to 20 or lower
        multiDexEnabled true
    }

    compileOptions {
        // Flag to enable support for the new language APIs
        coreLibraryDesugaringEnabled true

        // Sets Java compatibility to Java 8
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.2.2'
}

Если вы не выполните вышеуказанные действия, программа будет компилироваться и работать нормально для Android SDK 26 и выше.

Однако для Android SDK 25 и ниже она будет аварийно падать во время выполнения с ошибкой:

java.lang.NoClassDefFoundError: Failed resolution of: Ljava/time/LocalDate;

Вы можете поэкспериментировать здесь.

Синтаксический сахар

Прежде чем мы узнаем, что такое обессахаривание, давайте разберемся, что такое синтаксический сахар.

Это синтаксис в языке программирования, предназначенный для облегчения чтения или написания кода. Очень простой пример

В языке Си обозначение a[i] — это синтаксический сахар для *(a + i).

Следовательно, мы можем справедливо предположить, что какая-либо старая версия языка Си не поддерживает a[i].

В Android

В нашем случае можно предположить, что если в нашем коде есть LocalDate.now(), то он будет работать на устройствах с SDK 26 и выше, с тех пор, как там появился LocalDate.now().

Но на устройствах с SDK 25 и ниже он аварийно упадет, поскольку там нет LocalDate.now().

Можно считать LocalDate.now() чем-то вроде синтаксического сахара в Android SDK 26 и новее.

Обессахаривание

Концептуально, обессахаривание — это возвращение кода в исходную форму.

Простая иллюстрация. Предположим, что for — это новый синтаксический сахар для while. Обессахаривание — это просто преобразование его обратно к использованию while:

for (let i = 0; i < n; i:=i+1) {
  doSomething
}

// desugared

let i = 0;
while (i < n) {
  doSomething;
  i:=i+1
}

Другой способ взглянуть на desugaring — это как на шаг вперед к совместимости со старым SDK, обеспечивая поддержку нового синтаксического сахара.

Например, в Android SDK 25 и старше нет LocalDate.now(), но мы добавим поддержку совместимости оператора с обессахариванием по мере выпуска наших приложений.

Если приложение должно работать на устройстве с SDK 25 или ниже, у нас есть обессахаренный JDK, упакованный вместе с APK. С ним компиляция и выполнение проходят нормально.

Есть ли минусы в использовании обессахаривания?

Теоретически, когда мы компилируем наш APK, ориентированный на SDK 25 или старше без «десахара», размер составляет 6.3 Мб (debug вариант).

Однако, если мы используем Desugar, размер увеличивается до 12.1 Мб (debug вариант). Хотя это выглядит не очень хорошо из-за увеличения размера, это лучше, чем аварийное завершение работы приложения.

Что насчет SDK 26 и более новых версий

Когда я пытаюсь скомпилировать на SDK 26 или более новых версиях, размеры выглядят следующим образом

Похоже, что размер не сильно увеличивается, так как компиляция знает, что Desugaring JDK не требуется, когда мы отправляем наш APK на устройства с SDK 26 и новее.

Это здорово!

Источник

Exit mobile version