Android プラットフォーム - 第14部: Kotlin コンパイラの実験的機能に積極的に参加する
🌱 ブランチ: 14/opt-in-experimental-kotlin-compiler
🔗 リポジトリ: github.com/rsicarelli/kotlin-gradle-android-platform
⬅️ 前の記事: 第13部: 純粋なJVMモジュールを組み込む
➡️ 次の記事: 第15部: Detekt、Klint、Spotlessでコードをケアする
前回の記事では、JVMモジュールを宣言する能力をプラットフォームに追加しました。
この記事ではさらに一歩進んで、各モジュールが実験的な機能に「参加する」ためのコンパイルオプションを設定します。
KotlinでのOpt-In
APIを安全に設計するためにチームが採用する実践の一つに、特定の機能やAPIに対する「opt-in」制度の使用があります。
RequiresOptIn
アノテーション
RequiresOptIn
アノテーションは、明示的なopt-inを要求するAPIのためのマーカーである注釈クラスを示します。
@Target(ANNOTATION_CLASS)
@Retention(BINARY)
@SinceKotlin("1.3")
public annotation class RequiresOptIn(
val message: String = "",
val level: Level = Level.ERROR
) {
public enum class Level {
WARNING,
ERROR,
}
}
Contagiosidade
opt-inを要求するマーカーで注釈されたAPIは「感染性」があります。そのようなAPIを使ったり言及したりする他の宣言でもopt-inが求められます。
例えば:
@UnstableApi
class Unstable
@OptIn(UnstableApi::class)
fun foo(): Unstable = Unstable()
foo
関数を使用しようとすると、APIの不安定性を受け入れる必要があると警告されます。
OptIn
アノテーション
OptIn
アノテーションにより、マークされたAPIの使用に関連するリスクを認識して受け入れることを宣言できます。
@Target(
CLASS, PROPERTY, LOCAL_VARIABLE, VALUE_PARAMETER, CONSTRUCTOR, FUNCTION, PROPERTY_GETTER, PROPERTY_SETTER, EXPRESSION, FILE, TYPEALIAS
)
@Retention(SOURCE)
@SinceKotlin("1.3")
public annotation class OptIn(
vararg val markerClass: KClass<out Annotation>
)
実験的APIの使用
議論したことを具体例で見てみましょう。Material3
のコンポーネントでRequiresOptIn
で注釈されたものを使用します:
import androidx.compose.material3.Card
..
@Composable
fun HomeScreen() {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
//この行でIDEはエラー/警告を出します
Card(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.padding(all = 16.dp),
onClick = { },
content = {
DetailsScreen()
}
)
}
}
画面に表示されるエラー/警告に注意してください:
このエラーを解決するために、私たちは OptIn
を Composable 式に追加します:
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun HomeScreen() {
..
}
特定の状況にはこのアプローチが機能しますが、Flow.flatMapConcat
のように頻繁に使用される関数については、各使用ごとにこの宣言を繰り返すのは手間です。
OptIn
の必要性を避ける
Kotlin コンパイルをパーソナライズして applyKotlinOptions()
を構成して必要な機能でopt-inを行なうことができます。
1 - CompilationOptions
モデルを更新して FeatureOptIn
リストを受け入れるようにします:
data class CompilationOptions(
..
val featureOptIns: List<FeatureOptIn>,
) {
val extraFreeCompilerArgs: List<String>
get() = featureOptIns.map { "-opt-in=${it.flag}" }
enum class FeatureOptIn(val flag: String) {
ExperimentalMaterial3("androidx.compose.material3.ExperimentalMaterial3Api"),
ExperimentalCoroutinesApi(flag = "kotlinx.coroutines.ExperimentalCoroutinesApi"),
}
}
class CompilationOptionsBuilder {
..
private val featureOptInsBuilder = FeatureOptInBuilder()
fun optIn(vararg optIn: FeatureOptIn) {
featureOptInsBuilder.apply {
featureOptIns = optIn.toList()
}
}
internal fun build(): CompilationOptions = CompilationOptions(
..
featureOptIns = featureOptInsBuilder.build()
)
}
class FeatureOptInBuilder {
var featureOptIns: List<FeatureOptIn> = mutableListOf()
internal fun build(): List<FeatureOptIn> = featureOptIns.toList()
}
2 - fun applyKotlinOptions()
関数に移動して、使い方を更新します:
internal fun Project.applyKotlinOptions(compilationOptions: CompilationOptions) {
tasks.withType<KotlinCompile>().configureEach {
kotlinOptions {
allWarningsAsErrors = compilationOptions.allWarningsAsErrors
jvmTarget = compilationOptions.jvmTarget
compilerOptions.freeCompilerArgs.addAll(compilationOptions.extraFreeCompilerArgs)
}
}
}
3 - プロジェクトを同期します。次に、これらの機能を使用しているモジュールで新しいDSLを使用します:
import com.rsicarelli.kplatform.androidLibrary
import com.rsicarelli.kplatform.options.CompilationOptions.FeatureOptIn.ExperimentalCoroutinesApi
import com.rsicarelli.kplatform.options.CompilationOptions.FeatureOptIn.ExperimentalMaterial3
plugins {
id(libs.plugins.android.library.get().pluginId)
kotlin("android")
}
androidLibrary(
compilationOptionsBuilder = {
optIn(ExperimentalCoroutinesApi, ExperimentalMaterial3)
}
)
dependencies {
..
}
成功!
これで、CoroutinesとMaterial3の実験的な機能をOptIn
アノテーションを使わずに使用できます。
次の記事では、Detekt
とSpotless
を利用して静的解析を導入し、自動フォーマットとプロジェクトのコードスタイル(.editorconfig
)への準拠を進めることに重点を置きます。
こちらの記事はdev.toの良い記事を日本人向けに翻訳しています。
https://dev.to/rsicarelli/android-plataforma-parte-14-aderindo-a-funcionalidades-experimentais-do-compilador-do-kotlin-3b0g