Android TOML. Просто о каталогах зависимостей в Android Studio

Всем привет!

Меня зовут Евгений и я Android-разработчик. Сегодня хотел бы поделиться своими знаниями и наблюдениями относительно нового способа добавления зависимостей в проекты, созданные на базе Android Studio.

Предисловие

29.02.2024 вышла в stable новая версия Android Studio — Iguana. Вместе со сменой названия версии появилась возможность формировать зависимости в удобные каталоги формата .toml.

Актуальная версия Android Studio

Актуальная версия Android Studio


Лично для меня это было неожиданностью, так как об изменениях в новой версии я, в этот раз, не прочитал, а создание проектов «с нуля» у меня происходит редко, как правило, работаю над уже существующими проектами.

Но удивление было недолгим, после первого взгляда на блок зависимостей в новом проекте, стало понятно, что с этим можно разобраться и мне это уже знакомо. Подобное разделение зависимостей я уже встречал в крупных проектах и было предсказуемо, что однажды это станет стандартом для новых проектов в Android Studio.

dependencies {
    
    implementation(libs.androidx.core.ktx)
    implementation(libs.androidx.appcompat)
    implementation(libs.material)
    implementation(libs.androidx.activity)
    implementation(libs.androidx.constraintlayout)
    testImplementation(libs.junit)
    androidTestImplementation(libs.androidx.junit)
    androidTestImplementation(libs.androidx.espresso.core)
}

Хочется отметить, что блок добавления зависимостей стал выглядеть лучше, чем было до этого.

Разбираемся

Выбираем любую зависимость, переходим по ней (ctrl + ЛКН на Windows и Cmd + ЛКН на Mac OS) и попадаем в каталог зависимостей libs.versions.toml. Выглядит он так:

Слева видим, что libs.versions.toml лежит в Gradle Scripts.

Слева видим, что libs.versions.toml лежит в Gradle Scripts.


Каталог содержит три раздела:

[versions]

[libraries]

[plugins]

Из названий понятно, что в первом разделе нужно указать версию зависимости или плагина, во втором — зависимость для библиотек, в третьем каталоге указываем зависимость для плагинов.

Обращаю ваше внимание на то, что все необходимые данные указываем в формате String.

Если с добавлением версии плагина или библиотеки в резделе [versions]все очевидно, то формат добавления самой зависимости не так очевиден. Предлагаю добавить зависимость библиотеки room из пакета androidx сначала старым способом, а затем новым.

Добавляем зависимости

Старый способ

Если бы мы этот делали старым способом, то выглядело бы это так:

  1. Добавляем процессор аннотаций KSP в build.gradle.kts на уровне проекта, синхронизируем проект

plugins {
    alias(libs.plugins.androidApplication) apply false
    alias(libs.plugins.jetbrainsKotlinAndroid) apply false
    id("com.google.devtools.ksp") version "1.8.10-1.0.9" apply false
}
  1. Добавляем плагин для KSP в build.gradle.kts на уровне модуля (при создании нового проекта, по умолчанию, это модуль App), синхронизируем проект

    plugins {
        alias(libs.plugins.androidApplication)
        alias(libs.plugins.jetbrainsKotlinAndroid)
        id("com.google.devtools.ksp")
    }
  2. В блоке dependencies добавляем зависимости для библиотеки Room, annotationProcessor для работы с аннотациями Room и сам KSP для их обработки.

    dependencies {
        val room_version = "2.6.1"
    
        implementation("androidx.room:room-runtime:$room_version")
        annotationProcessor("androidx.room:room-compiler:$room_version")
        ksp("androidx.room:room-compiler:$room_version")
        
        implementation(libs.androidx.core.ktx)
        implementation(libs.androidx.appcompat)
        implementation(libs.material)
        implementation(libs.androidx.activity)
        implementation(libs.androidx.constraintlayout)
        testImplementation(libs.junit)
        androidTestImplementation(libs.androidx.junit)
        androidTestImplementation(libs.androidx.espresso.core)
    }

    Как мы видим, старый способ добавления зависимостей прекрасно работает с новым способом.

Новый способ

Для начала, разберем новый формат добавления зависимостей.

Как помним из примера выше, старым способом зависимость добавляется в формате

implementation("androidx.room:room-runtime:2.6.1)

Здесь мы видим:

implementation — сам метод, в который добавляется зависимость

androidx.room — пакет, в котором лежит библиотека

room-runtime — название библиотеки

2.6.1 — версия библиотеки

Точно таким же способом она разделена и в новом каталоге .toml:

Схема нового формата для добавления зависимостей и плагинов в .toml

Схема нового формата для добавления зависимостей и плагинов в .toml

На схеме видим, что в разделе [libraries] мы добавили строчку с зависимостью для библитеки Room и ее версию в разделе [versions].

Название зависимости — то, как мы называем свою зависимость. Имя произвольное, принято указывать с использованием kebab-case, то есть, через »-» (дефис или тире).

Далее в функциональных (фигурных) скобках указываем параметр group — то, как будет группироваться зависимость. Здесь нужно указать пакет библиотеки. Например, Room входит в пакет androix.room, соответственно, указываем именно так. Двоеточие ставить не нужно.

Следом указываем параметр name — это название библиотеки.

И в последнюю очередь, в параметр version.ref — версию библиотеки. Само же название версии в разделе [versions] принято указывать в camelCase. Синхронизируем проект.

Переходим в build.gradle.kts на уровне проекта и добавляем плагин KSP (обратите внимание, на предыдщем шаге он добавлен в [plugins]). Синхронизируем проект

plugins {
    alias(libs.plugins.androidApplication) apply false
    alias(libs.plugins.jetbrainsKotlinAndroid) apply false
    alias(libs.plugins.ksp) apply false
}

Переходим в build.gradle.kts на уровне модуля и добавляем плагин KSP. Синхронизируем проект.

plugins {
    alias(libs.plugins.androidApplication)
    alias(libs.plugins.jetbrainsKotlinAndroid)
    alias(libs.plugins.ksp)
}

В этом же файле добавляем нужные нам зависимости, указывая путь к ним в блоке dependencies:

dependencies {

    implementation(libs.androidx.room)
    annotationProcessor(libs.androidx.room.annotation.processor)
    ksp(libs.androidx.room.annotation.processor)

Обращаю ваше внимание на то, что несмотря на то, что название зависимостей в каталоге .toml мы добавляли через дефис, путь к файлам в build.gradle.kts нужно добавлять через точку.

Проверяем работу:

package com.gorovoyeg.newproject

import androidx.room.ColumnInfo
import androidx.room.Dao
import androidx.room.Database
import androidx.room.Entity
import androidx.room.PrimaryKey
import androidx.room.Query
import androidx.room.RoomDatabase

@Database(entities = [TestEntity::class] , version = 1, exportSchema = false)
abstract class TestDatabase: RoomDatabase() {

    abstract fun testDao(): TestDao
}

@Dao
interface TestDao {

    @Query("SELECT * FROM test_entity")
    fun testFunAll(): TestEntity
}

@Entity(tableName = "test_entity")
data class TestEntity(
    @PrimaryKey(autoGenerate = true) val testId: Int,
    @ColumnInfo(name = "test_name" ) val testName: String
)

Все работает отлично.

Подводим итоги

Как я и подкчеркнул в начале статьи — нововведение по добавлению зависимостей через каталог libs.versions.toml в новой версии Android Studio это вполне очевидная и предсказуемая мера со стороны Google. Для крупных действующих проектов это нововведение уже неактульно, так как многие самостоятельно уже разделяют зависимости более понятным и удобным способом, чем добавление зависимостей и их версий в блок dependencies в build.gradle. Тем не менее, считаю, что это приятное новое дополнение для разработчиков, которые стремятся к порядку в коде.

Использовать новый подход или нет — оставляю решение на ваше усмотрение. Лично я буду :-)

Спасибо за внимание.

© Habrahabr.ru