Android Studio делает успехи в поддержке Java 8 после того, как амбициозный, возможно, слишком амбициозный проект Jack & Jill был отложен. Что все это значит?
Версия 2.4 Android Studio приближается к выпуску-кандидату. в этот момент мы все получим возможность опробовать некоторые функции Java 8 — в частности, одну из тех, о которых программисты Android уже давно спрашивают, лямбды.
Последняя версия, предварительная версия 6, поддерживает удивительное количество функций Java 8, учитывая короткое время, прошедшее с момента прекращения поддержки проекта компилятора Jack & Jill. Проблема в том, что, хотя Android использует якобы стандартную Java, он компилирует ее в другой байт-код. Стандартный компилятор Java используется для преобразования в стандартный байт-код Java, а затем используется dx для преобразования его в байт-код Dalvik или Dex.
Проблема в том, что dx транслирует только подмножество байтового кода, и этого недостаточно для реализации функций Java 8. Проект компилятора Jack & Jill был попыткой создать совершенно новый компилятор, который перешел непосредственно с Java на байтовый код Dalvik. Это было бы еще большим отрывом от Java, и это якобы причина, по которой проект был отложен.
Теперь планируется расширить компилятор dx до так называемого desugar, чтобы скомпилировать дополнительные функции в байтовом коде, необходимые для реализации Java 8.
Последняя предварительная версия Android Studio включает в себя хороший набор функций Java 8, и, что наиболее важно, вы почти наверняка сможете использовать лямбды в следующем стабильном выпуске.
Что это значит для среднего программиста Android?
Как уже упоминалось, наибольшее влияние могут оказать лямбды. Причина в том, что у Java давно была проблема с отсутствием функций первого класса. Если вы хотите передать функцию в Java, вы должны передать объект, который имеет функцию как метод. Это делает обработку событий в Java очень многословной и почти непонятной для программиста, работающего практически с любого другого языка. Добавление лямбда-выражений значительно упрощает обработку событий.
Например, предположим, что у вас есть кнопка с кнопкой id, а затем, чтобы присоединить простой обработчик событий щелчка, вам необходимо использовать:
Button b=(Button) findViewById(R.id.button);
b.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
((Button)v).setText("You Clicked Me");
}
});
Здесь используется анонимный класс для создания экземпляра OnClickListener с переопределенным методом onClick.
Обратите внимание, что это класс и экземпляр класса и метод просто для передачи функции в setOnClickListener.
Это не так плохо, как кажется, потому что Android Studio сделает за вас большую часть работы, сгенерировав шаблонный код. Существует более простой способ создать обработчик событий для события щелчка, но он работает только для события щелчка.
Использование лямбда-выражений гораздо проще:
Button b=(Button) findViewById(R.id.button);
b.setOnClickListener(v->{b.setText("You Clicked ME!");});
Это просто передает функцию в setOnClickListener. Конечно, компилятор оборачивает функцию в экземпляр класса. но это все за кулисами, и программист может это игнорировать. Прежде чем вы подумаете, что есть ошибка в том, что в лямбде используется b, а не v, стоит также указать, что это закрытие, и лямбда имеет доступ к переменным, которые были в области видимости при создании. Однако кэшировать ссылки на объекты пользовательского интерфейса нецелесообразно, поэтому лучшая версия:
Button b=(Button) findViewById(R.id.button);
b.setOnClickListener(v->{((Button)v)
.setText("You Clicked ME!");});
Будет интересно узнать, знают ли в будущем какие-нибудь Android-программисты, что такое анонимный класс.
Вы также можете использовать ссылки на методы, которые позволяют ссылаться на существующий метод как на тело лямбда-выражения, что позволяет передавать существующий метод без передачи всего класса.
Вы также можете использовать аннотации типов, но только во время компиляции, а не во время выполнения, и если вы готовы отказаться от мгновенного выполнения, вы можете использовать методы по умолчанию и статические методы интерфейса. Позор, потому что методы по умолчанию очень полезны.
Также, если вы готовы использовать API 24 или выше, вы можете использовать:
java.lang.annotation.Repeatable AnnotatedElement.getAnnotationsByType(Class) java.util.stream java.lang.FunctionalInterface java.lang.reflect.Method.isDefault() java.util.function
Чтобы использовать эти функции, вы должны отключить Джека и любую другую библиотеку, которую вы используете, чтобы восполнить отсутствие поддержки Java 8. Вы также должны добавить:
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
в файл build.gradle модуля. После этого вы можете использовать Java 8 в новом проекте, в более старых проектах, возможно, придется сделать больше.
Будем надеяться, что в финальной версии у нас будет просто выпадающий список для уровня языка.
Android Studio по-прежнему меняется в одних отношениях слишком быстро, а в других — недостаточно быстро. Почему, например, мне все еще нужно использовать findById, а не привязку данных по умолчанию?
И почему все еще так медленно?