Jetpack Compose Compiler and Kotlin Versions Compatibility

Jetpack Compose コンパイラー と Kotlin バージョンの互換性、バージョンアップ時に確認が必要。

毎回、ググってるので貼っておく。


  repositories {
    google()
    mavenCentral()
  }

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


  buildFeatures {
    compose true
  }

  composeOptions {
    kotlinCompilerExtensionVersion versions.composeCompiler
  }

 

■ Compose to Kotlin Compatibility Map

Jetpack Compose Compiler and Kotlin versions Compatibility

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

 

■ JetBrains/kotlin/releases/latest

Releases Latest - JetBrains/kotlin
👉 Releases Latest - JetBrains/kotlin hatena-bookmark

 

■ compose - Google's Maven Repository

compose - Google's Maven Repository
👉 compose - Google's Maven Repository hatena-bookmark

 

■ Compose Compiler & Kotlin versions

Compose Compiler & Kotlin versions
👉 Compose Compiler Maven Index hatena-bookmark

 

■ 参考

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


3つの画像読み込みライブラリ Glide / Picasso / Coil - JetpackCompose 対応の状況

どれが、今、旬なのか。

まずはリンクを列挙しておきます。

全部使ってみようと思います。

giide vs picasso vs coil

👉 android glide, android picasso, android coil - 調べる - Google トレンド hatena-bookmark

 

Glide


32.8k stars
Watchers 1.1k watching
Forks 6k forks

👉 bumptech/glide: An image loading and caching library for Android focused on smooth scrolling hatena-bookmark

Glide

👉 Glide v4 : Fast and efficient image loading for Android hatena-bookmark

@sjudd Hey, I believe you're one of the maintainers of Glide. Is it a planned feature? Does Glide's team want help from the community on this? Jetpack Compose is going to stable soon, I believe later this month or next month

👉 Jetpack Compose Support · Issue #4459 · bumptech/glide hatena-bookmark

 

Picasso


18.3k stars
Watchers 867 watching
Forks 4k forks

👉 square/picasso: A powerful image downloading and caching library for Android hatena-bookmark

Picasso

👉 Picasso hatena-bookmark

Nobody works on Picasso. If you want something in the next N years definitely use Coil. Or Glide. Or whatever. They're all fine.

Image loading is a terrible, horrible business to be in. It's been really nice not being in that business for the last few years. I don't see a reason to resume. I certainly have no intent to support it anymore. Picasso accomplished its goal of moving the ecosystem out of the painful image loaders of 2011/2012 to the fluent and extensible ones we know today. But it's filled with technical debt and the legacy of poor design (at least, in hindsight) and is currently very, very stuck between a major refactor and redesign with no end in sight.

👉 Consider providing Jetpack Compose support · Issue #2203 · square/picasso hatena-bookmark

 

Coil


8.4k stars
Watchers 98 watching
Forks 512 forks

👉 coil-kt/coil: Image loading for Android backed by Kotlin Coroutines. hatena-bookmark

Coil

👉 Coil hatena-bookmark

To add support for Jetpack Compose, import the extension library:

implementation("io.coil-kt:coil-compose:2.1.0")

👉 Jetpack Compose - Coil hatena-bookmark

 

まとめ

JetpackCompose への対応ライブラリ群も見逃せません。

👉 skydoves/landscapist: 🍂 Jetpack Compose image loading library that fetches and displays network images with Glide, Coil, and Fresco hatena-bookmark

👉 wasabeef/composable-images: The Composable Images is a library providing Jetpack Compose wrapper for Glide, Picasso, and Coil. hatena-bookmark

アーキテクチャー、フレームワーク、ライブラリの選定はそのプロダクトの安定感に直結します。

機能確認を中心に検証しながら、将来の本筋を外してはなりません。

👉 画像読み込みライブラリ「COIL」 hatena-bookmark


【Jetpack Compose】Square 製 Radiography で View の構造を確認する

👉 square/radiography: Text-ray goggles for your Android UI. hatena-bookmark


dependencies {
  implementation 'androidx.compose.ui:ui-tooling:1.0.0-betaXY'
  implementation 'com.squareup.radiography:radiography:2.4.1'
}

scan() すると、画面のツリー構造がテキストで取得できるようでです。


DecorView { 1080×2160px }
├─LinearLayout { id:main, 1080×1962px }
│ ├─EditText { id:username, 580×124px, focused, text-length:0, ime-target }
│ ├─EditText { id:password, 580×124px, text-length:0 }
│ ╰─LinearLayout { 635×154px }
│   ├─Button { id:signin, 205×132px, text-length:7 }
│   ╰─Button { id:forgot_password, 430×132px, text-length:15 }
├─View { id:navigationBarBackground, 1080×132px }
╰─View { id:statusBarBackground, 1080×66px }


// Render the view hierarchy for all windows.
val prettyHierarchy = Radiography.scan()


// Extension function on View, renders starting from that view.
val prettyHierarchy = someView.scan()

 

Jetpack Compose でやってみる

この画面でやってみます。

square / radiography

Composable にコードを追加しておきます。


@Composable
fun HomeScreen(
  viewModel: HomeViewModel = hiltViewModel()
) {

  // ...

  val view: View = LocalView.current

  SideEffect {
    println(Radiography.scan())
    println(view.scan())
  }

}

👉 SideEffect - Compose における副作用  |  Jetpack Compose  |  Android Developers hatena-bookmark

 

結果


I: window-focus:false
I:  DecorView { 1080×2160px }
I:  ├─LinearLayout { 1080×2116px }
I:  │ ├─ViewStub { id:action_mode_bar_stub, GONE, 0×0px }
I:  │ ╰─FrameLayout { id:content, 1080×2039px }
I:  │   ╰─ComposeView { 1080×2039px }
I:  │     ╰─AndroidComposeView { 1080×2039px }
I:  │       ╰─CompositionLocalProvider { 1080×2039px }
I:  │         ╰─ScaffoldLayout { 1080×2039px }
I:  │           ├─<subcomposition of ScaffoldLayout>
I:  │           ├─<subcomposition of ScaffoldLayout>
I:  │           │ ╰─SnackbarHost
I:  │           ├─<subcomposition of ScaffoldLayout>
I:  │           ├─<subcomposition of ScaffoldLayout>
I:  │           │ ╰─CompositionLocalProvider { 1080×154px }
I:  │           │   ├─NavBottomBar { 1080×154px }
I:  │           │   │ ╰─Row { 1080×154px, SELECTABLE-GROUP }
I:  │           │   │   ├─BottomNavigationItem { 180×154px, roll:Tab, SELECTED }
I:  │           │   │   │ ╰─BottomNavigationTransition { 162×154px }
I:  │           │   │   │   ├─Box { 66×66px, layout-id:"icon" }
I:  │           │   │   │   │ ├─Icon
I:  │           │   │   │   │ │ ╰─RenderVectorGroup
I:  │           │   │   │   │ ╰─Icon { 66×66px }
I:  │           │   │   │   ╰─Box { 96×44px, layout-id:"label" }
I:  │           │   │   │     ╰─ProvideTextStyle { 96×44px, text-length:4 }
I:  │           │   │   ├─BottomNavigationItem { 180×154px, roll:Tab, SELECTED }
I:  │           │   │   │ ╰─BottomNavigationTransition { 151×154px }
I:  │           │   │   │   ├─Box { 66×66px, layout-id:"icon" }
I:  │           │   │   │   │ ├─Icon
I:  │           │   │   │   │ │ ╰─RenderVectorGroup
I:  │           │   │   │   │ ╰─Icon { 66×66px }
I:  │           │   │   │   ╰─Box { 85×44px, layout-id:"label" }
I:  │           │   │   │     ╰─ProvideTextStyle { 85×44px, text-length:5 }
I:  │           │   │   ├─BottomNavigationItem { 180×154px, roll:Tab, SELECTED }
I:  │           │   │   │ ╰─BottomNavigationTransition { 156×154px }
I:  │           │   │   │   ├─Box { 66×66px, layout-id:"icon" }
I:  │           │   │   │   │ ├─Icon
I:  │           │   │   │   │ │ ├─RenderVectorGroup
I:  │           │   │   │   │ │ ├─RenderVectorGroup
I:  │           │   │   │   │ │ ├─RenderVectorGroup
I:  │           │   │   │   │ │ ╰─RenderVectorGroup
I:  │           │   │   │   │ ╰─Icon { 66×66px }
I:  │           │   │   │   ╰─Box { 90×44px, layout-id:"label" }
I:  │           │   │   │     ╰─ProvideTextStyle { 90×44px, text-length:5 }
I:  │           │   │   ├─BottomNavigationItem { 180×154px, roll:Tab, SELECTED }
I:  │           │   │   │ ╰─BottomNavigationTransition { 150×154px }
I:  │           │   │   │   ├─Box { 66×66px, layout-id:"icon" }
I:  │           │   │   │   │ ├─Icon
I:  │           │   │   │   │ │ ╰─RenderVectorGroup
I:  │           │   │   │   │ ╰─Icon { 66×66px }
I:  │           │   │   │   ╰─Box { 84×44px, layout-id:"label" }
I:  │           │   │   │     ╰─ProvideTextStyle { 84×44px, text-length:4 }
I:  │           │   │   ├─BottomNavigationItem { 180×154px, roll:Tab, SELECTED }
I:  │           │   │   │ ╰─BottomNavigationTransition { 146×154px }
I:  │           │   │   │   ├─Box { 66×66px, layout-id:"icon" }
I:  │           │   │   │   │ ├─Icon
I:  │           │   │   │   │ │ ╰─RenderVectorGroup
I:  │           │   │   │   │ ╰─Icon { 66×66px }
I:  │           │   │   │   ╰─Box { 80×44px, layout-id:"label" }
I:  │           │   │   │     ╰─ProvideTextStyle { 80×44px, text-length:4 }
I:  │           │   │   ╰─BottomNavigationItem { 180×154px, roll:Tab, SELECTED }
I:  │           │   │     ╰─BottomNavigationTransition { 180×154px }
I:  │           │   │       ├─Box { 66×66px, layout-id:"icon" }
I:  │           │   │       │ ├─Icon
I:  │           │   │       │ │ ╰─RenderVectorGroup
I:  │           │   │       │ ╰─Icon { 66×66px }
I:  │           │   │       ╰─Box { 114×44px, layout-id:"label" }
I:  │           │   │         ╰─ProvideTextStyle { 114×44px, text-length:8 }
I:  │           │   ╰─AdaptiveAd { 1080×0px }
I:  │           │     ╰─ViewFactoryHolder { 1080×0px }
I:  │           │       ╰─AdView { 1080×0px }
I:  │           │         ╰─FrameLayout { 0×0px }
I:  │           ╰─<subcomposition of ScaffoldLayout>
I:  │             ╰─NavHost
I:  │               ╰─Box
I:  │                 ╰─LocalOwnersProvider
I:  │                   ├─TopBar
I:  │                   │ ╰─CompositionLocalProvider
I:  │                   │   ├─Row
I:  │                   │   │ ╰─CompositionLocalProvider { roll:Button }
I:  │                   │   │   ├─CompositionLocalProvider
I:  │                   │   │   │ ╰─RenderVectorGroup
I:  │                   │   │   ╰─CompositionLocalProvider
I:  │                   │   ├─Row
I:  │                   │   │ ╰─ProvideTextStyle { text-length:4 }
I:  │                   │   ╰─CompositionLocalProvider
I:  │                   ╰─Column
I:  │                     ├─Button { roll:Button }
I:  │                     │ ╰─CompositionLocalProvider
I:  │                     │   ╰─Text { text-length:7 }
I:  │                     ├─Spacer
I:  │                     ├─Button { roll:Button }
I:  │                     │ ╰─CompositionLocalProvider
I:  │                     │   ╰─Text { text-length:7 }
I:  │                     ├─Spacer
I:  │                     ├─Button { roll:Button }
I:  │                     │ ╰─CompositionLocalProvider
I:  │                     │   ╰─Text { text-length:7 }
I:  │                     ├─Spacer
I:  │                     ╰─Button { roll:Button }
I:  │                       ╰─CompositionLocalProvider
I:  │                         ╰─Text { text-length:5 }
I:  ├─View { id:navigationBarBackground, 1080×44px }
I:  ╰─View { id:statusBarBackground, 1080×77px }

I: AndroidComposeView:
I: window-focus:false
I:  AndroidComposeView { 1080×2039px }
I:  ╰─CompositionLocalProvider { 1080×2039px }
I:    ╰─ScaffoldLayout { 1080×2039px }
I:      ├─<subcomposition of ScaffoldLayout>
I:      ├─<subcomposition of ScaffoldLayout>
I:      │ ╰─SnackbarHost
I:      ├─<subcomposition of ScaffoldLayout>
I:      ├─<subcomposition of ScaffoldLayout>
I:      │ ╰─CompositionLocalProvider { 1080×154px }
I:      │   ├─NavBottomBar { 1080×154px }
I:      │   │ ╰─Row { 1080×154px, SELECTABLE-GROUP }
I:      │   │   ├─BottomNavigationItem { 180×154px, roll:Tab, SELECTED }
I:      │   │   │ ╰─BottomNavigationTransition { 162×154px }
I:      │   │   │   ├─Box { 66×66px, layout-id:"icon" }
I:      │   │   │   │ ├─Icon
I:      │   │   │   │ │ ╰─RenderVectorGroup
I:      │   │   │   │ ╰─Icon { 66×66px }
I:      │   │   │   ╰─Box { 96×44px, layout-id:"label" }
I:      │   │   │     ╰─ProvideTextStyle { 96×44px, text-length:4 }
I:      │   │   ├─BottomNavigationItem { 180×154px, roll:Tab, SELECTED }
I:      │   │   │ ╰─BottomNavigationTransition { 151×154px }
I:      │   │   │   ├─Box { 66×66px, layout-id:"icon" }
I:      │   │   │   │ ├─Icon
I:      │   │   │   │ │ ╰─RenderVectorGroup
I:      │   │   │   │ ╰─Icon { 66×66px }
I:      │   │   │   ╰─Box { 85×44px, layout-id:"label" }
I:      │   │   │     ╰─ProvideTextStyle { 85×44px, text-length:5 }
I:      │   │   ├─BottomNavigationItem { 180×154px, roll:Tab, SELECTED }
I:      │   │   │ ╰─BottomNavigationTransition { 156×154px }
I:      │   │   │   ├─Box { 66×66px, layout-id:"icon" }
I:      │   │   │   │ ├─Icon
I:      │   │   │   │ │ ├─RenderVectorGroup
I:      │   │   │   │ │ ├─RenderVectorGroup
I:      │   │   │   │ │ ├─RenderVectorGroup
I:      │   │   │   │ │ ╰─RenderVectorGroup
I:      │   │   │   │ ╰─Icon { 66×66px }
I:      │   │   │   ╰─Box { 90×44px, layout-id:"label" }
I:      │   │   │     ╰─ProvideTextStyle { 90×44px, text-length:5 }
I:      │   │   ├─BottomNavigationItem { 180×154px, roll:Tab, SELECTED }
I:      │   │   │ ╰─BottomNavigationTransition { 150×154px }
I:      │   │   │   ├─Box { 66×66px, layout-id:"icon" }
I:      │   │   │   │ ├─Icon
I:      │   │   │   │ │ ╰─RenderVectorGroup
I:      │   │   │   │ ╰─Icon { 66×66px }
I:      │   │   │   ╰─Box { 84×44px, layout-id:"label" }
I:      │   │   │     ╰─ProvideTextStyle { 84×44px, text-length:4 }
I:      │   │   ├─BottomNavigationItem { 180×154px, roll:Tab, SELECTED }
I:      │   │   │ ╰─BottomNavigationTransition { 146×154px }
I:      │   │   │   ├─Box { 66×66px, layout-id:"icon" }
I:      │   │   │   │ ├─Icon
I:      │   │   │   │ │ ╰─RenderVectorGroup
I:      │   │   │   │ ╰─Icon { 66×66px }
I:      │   │   │   ╰─Box { 80×44px, layout-id:"label" }
I:      │   │   │     ╰─ProvideTextStyle { 80×44px, text-length:4 }
I:      │   │   ╰─BottomNavigationItem { 180×154px, roll:Tab, SELECTED }
I:      │   │     ╰─BottomNavigationTransition { 180×154px }
I:      │   │       ├─Box { 66×66px, layout-id:"icon" }
I:      │   │       │ ├─Icon
I:      │   │       │ │ ╰─RenderVectorGroup
I:      │   │       │ ╰─Icon { 66×66px }
I:      │   │       ╰─Box { 114×44px, layout-id:"label" }
I:      │   │         ╰─ProvideTextStyle { 114×44px, text-length:8 }
I:      │   ╰─AdaptiveAd { 1080×0px }
I:      │     ╰─ViewFactoryHolder { 1080×0px }
I:      │       ╰─AdView { 1080×0px }
I:      │         ╰─FrameLayout { 0×0px }
I:      ╰─<subcomposition of ScaffoldLayout>
I:        ╰─NavHost
I:          ╰─Box
I:            ╰─LocalOwnersProvider
I:              ├─TopBar
I:              │ ╰─CompositionLocalProvider
I:              │   ├─Row
I:              │   │ ╰─CompositionLocalProvider { roll:Button }
I:              │   │   ├─CompositionLocalProvider
I:              │   │   │ ╰─RenderVectorGroup
I:              │   │   ╰─CompositionLocalProvider
I:              │   ├─Row
I:              │   │ ╰─ProvideTextStyle { text-length:4 }
I:              │   ╰─CompositionLocalProvider
I:              ╰─Column
I:                ├─Button { roll:Button }
I:                │ ╰─CompositionLocalProvider
I:                │   ╰─Text { text-length:7 }
I:                ├─Spacer
I:                ├─Button { roll:Button }
I:                │ ╰─CompositionLocalProvider
I:                │   ╰─Text { text-length:7 }
I:                ├─Spacer
I:                ├─Button { roll:Button }
I:                │ ╰─CompositionLocalProvider
I:                │   ╰─Text { text-length:7 }
I:                ├─Spacer
I:                ╰─Button { roll:Button }
I:                  ╰─CompositionLocalProvider
I:                    ╰─Text { text-length:5 }

どう使います?、これ。

scan() 時のオプションもいろいろあるようなので試してみますか。