Kotlinのライブラリをバージョンカタログで管理してみた
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.kts
のdependencies
の記述を減らすことも可能。
もちろん、[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
■手順
-
Emptyの適当なプロジェクトを作る
-
どこでもいいから右クリックメニューから、New -> VersionCatalogを選択する
-
名前をつけると、空のtomlファイルが作成される(※)
-
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 は、読みやすく、辞書に明確にマッピングし、さまざまなデータ構造に簡単に解析できるようにすることを目指しています。
◆実装してみての感想
正直、小規模アプリでは実装する旨味は少ないかな〜と思った。マルチモジュールを何個も作ってる環境だと一元管理できる分、めちゃくちゃ便利になりそう。
逆に、マルチモジュール環境で一元管理してないと、ライブラリのバージョンアップするにも、「どのモジュールにバージョンアップしたいライブラリが入ってたっけ?」などの手間がかかったり、うっかり漏れたりしそうだからストレス溜まりそう。
あとは、ライブラリのバージョンがぱっと見で見やすいっていうのが好き。
ぱっと見でわかりやすいは正義。(透明性信者)
◆参考記事
Discussion