【Jetpack Compose】Compose (androidx.compose.*) のバージョンが分かれている件

元は、こんな感じで問題ありませんでした。


ext.versions = [
  'kotlin'  : '1.6.21'
  'compose' : '1.2.0-rc02'
]

dependencies {
  classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
}

composeOptions {
  kotlinCompilerExtensionVersion versions.compose
}


implementation "androidx.compose.material:material:${versions.compose}"
implementation "androidx.compose.material:material-icons-extended:${versions.compose}"
implementation "androidx.compose.ui:ui:${versions.compose}"
implementation "androidx.compose.ui:ui-tooling-preview:${versions.compose}"
debugImplementation "androidx.compose.ui:ui-tooling:${versions.compose}"
debugImplementation "androidx.compose.ui:ui-test-manifest:${versions.compose}"
androidTestImplementation "androidx.compose.ui:ui-test-junit4:${versions.compose}"

アップデート通知が出たので、いつものように


1.3.0-alpha01

に上げました。


ext.versions = [
  'kotlin'  : '1.6.21'
  'compose': '1.3.0-alpha01'
]

...

ビルドできなくなりました。

なんでや。

 

■ kotlin と compose の関係

kotlin と compose には、お互いに対応するバージョンが決まっていましたね!

Compose to Kotlin Compatibility Map

👉 Compose to Kotlin Compatibility Map  |  Android Developers hatena-bookmark

あれ、compose「1.3.0-alpha01」がないよ!

 

■ 「Compose」 は1つではない

Jetpack Compose is multiple things under one name:

- A compiler plugin that helps efficiently calculate the difference between two in-memory tree data structures
- A new UI toolkit for Android
- A new UI toolkit for desktop apps (Compose Desktop)

👉 Drop "androidx" from Jetpack Compose package name, for multiplatform, before 1​.​0 release. · Change.org hatena-bookmark

どうやら、Android でいうと compose は

- compose compiler
- compose ui toolkit

の2つに分かれているようです

👉 This version (1.2.0-alpha08) of the Compose Compiler requires Kotlin version 1.6.20 but you appear to be using Kotlin version 1.6.21 which is not known to be compatible. hatena-bookmark

 

■ まとめ

上記2つのことを考慮して書き換えます。


ext.versions = [
  'kotlin'    : '1.7.0'
  'compose'   : '1.2.0',         // compose-compiler
  'composeUi' : '1.3.0-alpha01'  // compose-ui
]

dependencies {
  classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
}

composeOptions {
  kotlinCompilerExtensionVersion versions.compose // compose-compiler
}

// compose-ui
implementation "androidx.compose.material:material:${versions.composeUi}"
implementation "androidx.compose.material:material-icons-extended:${versions.composeUi}"
implementation "androidx.compose.ui:ui:${versions.composeUi}"
implementation "androidx.compose.ui:ui-tooling-preview:${versions.composeUi}"
debugImplementation "androidx.compose.ui:ui-tooling:${versions.composeUi}"
debugImplementation "androidx.compose.ui:ui-test-manifest:${versions.composeUi}"
androidTestImplementation "androidx.compose.ui:ui-test-junit4:${versions.composeUi}"

👉 This version (1.2.0-alpha08) of the Compose Compiler requires Kotlin version 1.6.20 but you appear to be using Kotlin version 1.6.21 which is not known to be compatible. hatena-bookmark


Kotlin 今どきよくある JSON リクエストからのパース

数年で一気に変わってます、JSONの取り扱い処理。

GsonMoshi も不要です。

Kotlin 内蔵の serialization を使うのが良いでしょう。

👉 Kotlin/kotlinx.serialization: Kotlin multiplatform / multi-format serialization hatena-bookmark


@Provides
@Singleton
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
  val contentType = "application/json".toMediaType()
  val json = Json { 
    ignoreUnknownKeys = true
    isLenient = true
  } // *
  return Retrofit.Builder()
    .client(okHttpClient)
    .baseUrl(BASE_URL)
    .addConverterFactory(json.asConverterFactory(contentType))
    .build()
}

処理時に便利に設定を変えられるようになっているので、

よくあるやつを並べておきます。

https://api.cryptowat.ch/markets/prices
👉 【仮想通貨】Cryptowatch Public Market REST API を眺める hatena-bookmark

 

ignoreUnknownKeys = true

デフォルトでは、逆シリアル化中に不明なキーが検出されるとエラーが発生します。 これを回避し、ignoreUnknownKeysプロパティをtrueに設定することで、このようなキーを無視できます。

👉 kotlinx.serialization/json.md at master · Kotlin/kotlinx.serialization hatena-bookmark

公開されている WEB-API には不要なデータがたくさんあります。

それを無視するための設定です。

 

isLenient = true

デフォルトでは、JsonパーサーはさまざまなJSON制限を強制して、可能な限り仕様に準拠します(RFC-4627を参照)。 特に、キーは引用符で囲まれている必要があり、リテラルは引用符で囲まれていない必要があります。 これらの制限は、isLenientプロパティを使用して緩和できます。 isLenient = trueを使用すると、非常に自由にフォーマットされたデータを解析できます。

私はどうしても必要なときにしか使いません。

RFCに基づかないJSONは一応留意しておきたいので。

👉 kotlinx.serialization/json.md at master · Kotlin/kotlinx.serialization hatena-bookmark
👉 RFC 4627 - The application/json Media Type for JavaScript Object Notation (JSON) hatena-bookmark

 

まとめ

一度、テンプレート化しておくと、当分使い回すことができます。

調べるときに、いろいろ古い情報が多くて時間かかったので、メモとして。

👉 【Retorofit】コピペで使える NetworkModule【Dagger Hilt】 hatena-bookmark
👉 Kotlin/kotlinx.serialization: Kotlin multiplatform / multi-format serialization hatena-bookmark



【Jetpack Compose】Compose Settings で数分で設定画面を作る

意外と面倒な設定画面が数分でできます。

This library provides a set of Settings like composable items to help android Jetpack Compose developers build complex settings screens without all the boilerplate

このライブラリは、開発者がボイラープレートなしで複雑な設定画面を構成できるアイテム詰め合わせです。

👉 alorma/Compose-Settings: Android #JetpackCompose Settings library hatena-bookmark

以下コピペですぐに表示できます。


implementation 'com.github.alorma:compose-settings-ui:$version'


SettingsMenuLink(
  icon = { Icon(imageVector = Icons.Default.Wifi, contentDescription = "Wifi") },
  title = { Text(text = "Link") },
  subtitle = { Text(text = "This is a longer text") },
  onClick = {},
)
Divider()
SettingsSwitch(
  icon = { Icon(imageVector = Icons.Default.Wifi, contentDescription = "Wifi") },
  title = { Text(text = "Switch") },
  subtitle = { Text(text = "This is a longer text") },
  onCheckedChange = { },
)
Divider()
SettingsCheckbox(
  icon = { Icon(imageVector = Icons.Default.Wifi, contentDescription = "Wifi") },
  title = { Text(text = "Checkbox") },
  subtitle = { Text(text = "This is a longer text") },
  onCheckedChange = { },
)
Divider()
SettingsSlider(
  icon = {
    Icon(
      imageVector = Icons.Default.BrightnessMedium,
      contentDescription = "Brightness Medium"
    )
  },
  title = { Text(text = "Slider") },
)
Divider()
SettingsList(
  title = { Text(text = "List") },
  subtitle = { Text(text = "Select a fruit") },
  items = listOf("Banana", "Kiwi", "Pineapple"),
  action = {
    IconButton(onClick = {  }) {
      Icon(
        imageVector = Icons.Default.Clear,
        contentDescription = "Clear",
      )
    }
  },
)

alorma/Compose-Settings: Android #JetpackCompose Settings library


UIだけでなく Preferences への読み書きも用意されています。


implementation 'com.github.alorma:compose-settings-storage-preferences:$version'

state を更新するとそのまま Preferences に書き込みされます。


val preferenceStorage = rememberPreferenceBooleanSettingState(
    key = "switch",
    defaultValue = false,
)
SettingsCheckbox(
    state = preferenceStorage, // *
    icon = {

超便利です!!

コードも良い参考にもなります。

👉 【Jetpack Compose】Icon() や Image() で ImageVector をより便利に使う hatena-bookmark