🏄‍♂️

Kotlinのライブラリをバージョンカタログで管理してみた

2023/10/03に公開

KotlinでAndroidアプリ開発すると、いろんなライブラリを入れる必要性が、まぁ出てくる出てくる...。

その中で、androidX関連のライブラリだと、新しいメソッドが出てきたり、ExterminalがStableになったりして、バージョン上げたいなぁと思うけど、プロジェクトをマルチモジュール化して個別にライブラリをインストールしている場合、全部を変更しないといけないのが、手間でしょうがない。

そこで、バージョンカタログで一元管理しておけば、そのカタログだけ直せば、全部のモジュールに反映されるので便利。

あと、単純にライブラリごとのバージョン管理が見やすくて楽。

◆定義方法

■デフォルトでのライブラリ定義

build.gradle.kts(app直下)

AndroidのEmptyプロジェクト作った直後のapp直下のbuild.gradle.ktsにあるdependenciesの記述がこれ

dependencies {

    implementation("androidx.core:core-ktx:1.9.0")
    implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
    implementation("androidx.activity:activity-compose:1.7.2")
    implementation(platform("androidx.compose:compose-bom:2023.03.00"))
    implementation("androidx.compose.ui:ui")
    implementation("androidx.compose.ui:ui-graphics")
    implementation("androidx.compose.ui:ui-tooling-preview")
    implementation("androidx.compose.material3:material3")
    testImplementation("junit:junit:4.13.2")
    androidTestImplementation("androidx.test.ext:junit:1.1.5")
    androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
    androidTestImplementation(platform("androidx.compose:compose-bom:2023.03.00"))
    androidTestImplementation("androidx.compose.ui:ui-test-junit4")
    debugImplementation("androidx.compose.ui:ui-tooling")
    debugImplementation("androidx.compose.ui:ui-test-manifest")
}

うん、まぁ、なんというか、ぱっと見だと「バージョンどれだよ?」って感じの記述ですよね...うん...わかりにくい。

一応、「:」のあとの数字が各ライブラリのバージョン指定となっていますけど、見にくいったらありゃしない。

■バージョンカタログでのライブラリ定義

これを、バージョンカタログで、各ライブラリのバージョン管理してみるとこんな感じになる。

libs.version.toml

[versions]
androidx-core = "1.9.0"
androidx-lifecycle = "2.6.2"
androidx-activity = "1.7.2"

[libraries]

androidx-core = { module = "androidx.core:core-ktx", version.ref = "androidx-core" }
androidx-lifecycle = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "androidx-lifecycle" }
androidx-activity = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity"}


[plugins]

[bundles]

定義名は任意。なんでもいい。

バージョンは、[versions]で、定義したものを、[libraries]で指定するときに、version.ref="([version]で定義した定義名)"という感じで指定する。

個人的には、ライブラリ名とバージョン定義名は同じにしておいたほうが、変なミスが減りそうなので推奨

build.gradle.kts(app直下)


dependencies {

// デフォルトで定義されてたものをコメントアウト
//    implementation("androidx.core:core-ktx:1.9.0")
//    implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
//    implementation("androidx.activity:activity-compose:1.7.2")

// バージョンカタログ参照の書き方に置換
    implementation(libs.androidx.core)
    implementation(libs.androidx.lifecycle)
    implementation(libs.androidx.activity)
    
    ...
}

こうすることで、従来どおりにビルドすることが可能。(libs.version.tomlで新しく定義を増やしたあとは、1回同期しないと、build.gradle.ktsでの参照ができないので注意)

■バージョンカタログのパッケージ単位でのライブラリ定義

さらに、ライブラリをバンドルで定義することによって、複数のライブラリをパッケージ単位でインストールすることも可能。

libs.version.toml

[bundles]のところだけ追加

[versions]
androidx-core = "1.9.0"
androidx-lifecycle = "2.6.2"
androidx-activity = "1.7.2"

[libraries]

androidx-core = { module = "androidx.core:core-ktx", version.ref = "androidx-core" }
androidx-lifecycle = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "androidx-lifecycle" }
androidx-activity = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity"}


[plugins]

[bundles]
androidx-base = [
    #[libraries]の定義名を文字列として指定する
    "androidx-core",
    "androidx-lifecycle",
    "androidx-activity",
]

build.gradle.kts(app直下)


dependencies {

// デフォルトで定義されてたものをコメントアウト
//    implementation("androidx.core:core-ktx:1.9.0")
//    implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
//    implementation("androidx.activity:activity-compose:1.7.2")

// バージョンカタログ参照の書き方をコメントアウト
//    implementation(libs.androidx.core)
//    implementation(libs.androidx.lifecycle)
//    implementation(libs.androidx.activity)

// バージョンカタログのバンドル参照の書き方に置換
    implementation(libs.bundles.androidx.base)
    
    ...
}

こうすることで、まとめてインストールできて、build.gradle.ktsdependenciesの記述を減らすことも可能。

もちろん、[libraries][bundles]を併用して記述することも可能。

◆細かいけど大事なこと

libs.version.tomlで定義したライブラリ名に「 - (ハイフン)」が含めれているものをbuild.gradle.ktsで参照するときは、「 - (ハイフン)」部分は「 . (ドッド)」での参照に変わる。

libs.version.toml

[libraries]

androidx-core = { module = "androidx.core:core-ktx", version.ref = "androidx-core" }

build.gradle.kts(app直下)


dependencies {

// `libs.version.toml`では、`android-core`の名前で定義しているが、`dependencies`では`libs.androidx.core`で参照される
    implementation(libs.androidx.core)
    
    ...
}

なんでかはよくわからない。

◆実装方法

それでは、実装方法について説明していきます。

といっても、そんなに大層なことするわけじゃないので、誰でも簡単にできます。

■環境

Android Studio Giraffe | 2022.3.1 Patch 1

■手順

  1. Emptyの適当なプロジェクトを作る

  2. どこでもいいから右クリックメニューから、New -> VersionCatalogを選択する

  3. 名前をつけると、空のtomlファイルが作成される(※)

  4. tomlファイルにインストールしたいライブラリと紐づくバージョンを記載して、build.gradle.ktsから参照させる(書き方は 定義方法 参照)

(※)デフォルト名は、「libs」で、libs.version.tomlがプロジェクト直下の「gradle」フォルダ直下に作成される

◆小ネタ

■サジェスト

[libraries]に定義するとき、[module = "", version.ref = ""]の形式だと、module = ""のときに、サジェストが出ない問題あり。バージョン情報含めた、従来の定義方法(下記画像)だとサジェストでるので、これを流用してtomlを作成した。(サジェストでるのは、公式系のライブラリだけっぽい)

[module = "", version.ref = ""]形式でもサジェスト出てくれれば、そこそこ便利。

まぁ、dependenciesにあるものをコピペするなら関係ないお話

■定義バージョンが最新バージョンではないときに出てくるハイライト

たまに dependenciesを見てみると、AndroidStudioで黄色くハイライトしていて、マウスオーバーすると、「新しいバージョンあります!」的なニュアンスの文言が表示される。

この機能はtomlでも出てくるので、ぱっと見で新しいバージョンがあるかどうか把握できる。

version = ""指定

[libraries]に定義するとき、version.ref = "([versions]の定義名)"ではなく、version = "(バージョンの数字)"で、バージョンを直接指定しても、動作的には問題ない。

libs.version.toml

[libraries]

androidx-core = { module = "androidx.core:core-ktx", version = "1.9.0" }

ただ、バージョンカタログなのに、[versions]に集約してないのは、あんまり意味をなしていない思うので、バージョン直接指定は使わない方向のほうが良さそう。

■その他設定

他記事には、「◯◯設定しないと動作しない...」とか書いてあったけど、執筆時点の環境では、本記事に書かれている以外の設定は、特に何もしなくても動作する。

■.tomlの意味

拡張子の意味を理解して、ファイルの役割の理解を深めていくぅ!(下記引用)

TOML (Tom’s Obvious Minimal Language) は、.toml 拡張子を使用する最小限の構成ファイル形式です。 TOML は、読みやすく、辞書に明確にマッピングし、さまざまなデータ構造に簡単に解析できるようにすることを目指しています。

https://docs.fileformat.com/ja/programming/toml/

◆実装してみての感想

正直、小規模アプリでは実装する旨味は少ないかな〜と思った。マルチモジュールを何個も作ってる環境だと一元管理できる分、めちゃくちゃ便利になりそう。

逆に、マルチモジュール環境で一元管理してないと、ライブラリのバージョンアップするにも、「どのモジュールにバージョンアップしたいライブラリが入ってたっけ?」などの手間がかかったり、うっかり漏れたりしそうだからストレス溜まりそう。

あとは、ライブラリのバージョンがぱっと見で見やすいっていうのが好き。

ぱっと見でわかりやすいは正義。(透明性信者)

◆参考記事

https://developer.android.com/studio/build/migrate-to-catalogs?hl=ja

Discussion