-
Notifications
You must be signed in to change notification settings - Fork 0
학습‐desugaring이란
desugaring을 한국어로 번역하면 설탕을 없애다 뜻이다.
프로그래밍에서는 syntatic sugar
를 제거하여 기초적인 형태로 변환하는 과정을 의미한다.
Python을 예로 들어보면 list comprehension
이 있다.
다음과 같은 코드가 있다고 해보자
squares = [x**2 for x in range(5)]
이 코드는 0부터 4까지의 숫자를 제곱한 [0, 1, 4, 9, 16]
의 값을 반환한다.
그렇지만 이 문법을 일반 for loop
로도 바꿀 수 있다.
squares = []
for x in range(5):
squares.append(x**2)
list comprehension
이 syntatic sugar
역할을 하여 코드가 간결해보이지만 반복문을 사용하여 리스트를 생성하는 방식으로 변환될 수 있는 것이다.
이처럼 안드로이드에서의 desugaring
도 마찬가지의 의미이다.
Android SDK24 에서는 java8의 일부 기능만 지원을 하고 어떤 것은 호환이 되지 않는다. 안드로이드 개발에서 사용하는 Java 버전은 항상 최신 버전을 따라가지 않기 때문에 이 기능을 호환이 가능하도록 해줘야 한다.
java8의 주요 기능으로는 Lambda Expression
, Method References
, java.time
등이 있다.
desugaring 과정은 아래 사진과 같이 진행된다.
AGP는 java8의 일부 기능을 기본적으로 지원해준다.
하지만 java.time
과 같은 기능을 사용하려면 Java 기능을 더 기본적인 형태로 변환하는 bytecode 변환 과정을 거쳐야한다.
이렇게 변환된 코드는 안드로이드가 지원하는 DEX 코드로 컴파일되어서 하위 버전의 안드로이드에서도 실행될 수 있다.
이 AGP의 desugar과정은 D8/R8 Compiler
수행한다. D8/R8 Compiler
는 안드로이드의 byte코드를 DEX코드로 컴파일 하는 도구이다. 이 과정에서 java8 기능을 사용 가능하도록 변환해주기 때문에 자유롭게 사용할 수 있다.
설정도 매우 간단하다.
android {
defaultConfig {
// Required when setting minSdkVersion to 20 or lower
multiDexEnabled = true
}
compileOptions {
// Flag to enable support for the new language APIs
// For AGP 4.1+
isCoreLibraryDesugaringEnabled = true
// For AGP 4.0
// coreLibraryDesugaringEnabled = true
// Sets Java compatibility to Java 8
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
dependencies {
// For AGP 7.4+
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.3")
// For AGP 7.3
// coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.2.3")
// For AGP 4.0 to 7.2
// coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.1.9")
}
이렇게 설정을 해주고 gradle sync를 해주면 된다.
공식문서에서는 뭔가 java8버전에 대한 설명이 대부분이여서 java8까지만 지원하는 것 같아서 테스트를 진행해봤다.
sourceCompatibility
와 targetCompatibility
그리고 kotlin jvmTarget
을 17로 바꿔보고서 진행을 했다.
아래와 같이 Java14버전부터 나오고 17부터 안정화된 switch case 문을 작성하였다.
Test.java
public class Test {
public static int getDayValue(String day) {
return switch (day) {
case "MONDAY", "FRIDAY", "SUNDAY" -> 6;
case "TUESDAY" -> 7;
default -> 0;
};
}
}
그리고서 이 코드를
@Composable
fun Greeting(
name: String,
modifier: Modifier = Modifier,
) {
val x = Test.getDayValue("MONDAY")
Column {
Text(
text = "Hello $name!",
modifier = modifier,
)
Text(
text = "Hello $x!",
modifier = modifier,
)
Text(
text = "Hello $name!",
modifier = modifier,
)
Button(
onClick = {
Log.d("TAG", "Button clicked")
},
modifier = modifier,
) {
Text("Click me")
}
}
}
이렇게 사용해봤다.
이렇게 한뒤 API 26으로 실행결과
문제 없이 잘 나오는 것을 확인할 수 있었다.
마찬가지로 java17 버전부터 나온 record 문법을 사용해도 빌드는 잘 되는 것을 확인했다.
그런데 여러가지 실험을 하는 중에 java17 문법부터 추가된 stream.toList()가 실행이 안되는 것을 알 수 있었다. 이 부분에 대해서는 추측이지만 17버전 문법도 전부다 지원하지는 않는 것 같다.
Reference https://developer.android.com/studio/write/java8-support