Всем привет!

Меня зовут Евгений и я 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 {
    ...
    id("com.google.devtools.ksp") version "1.8.10-1.0.9" apply false
}
  1. Добавляем плагин для KSP в build.gradle.kts на уровне модуля (при создании нового проекта, по умолчанию, это модуль App), синхронизируем проект

    plugins {
        ...
        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("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.ksp) apply false
}

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

plugins {
    ...
    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. Тем не менее, считаю, что это приятное новое дополнение для разработчиков, которые стремятся к порядку в коде.

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

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

Комментарии (3)


  1. fellow_pablo
    19.03.2024 10:02

    В примере, как я понял, показывается подключение Room, но при этом в в блоке dependency присутствуют и другие библиотеки, которые в блоке "после" вдруг пропадают, из-за чего несколько сложнее было понять принцип работы. Было бы удобнее, если бы в примерах было только то, что относится к либе Room, т.к. мне пришлось лезть в офф доки, чтобы полностью понять принцип работы.

    А по теме нововведения: за время опыта работы с Cargo очень полюбил toml формат, поэтому одобряю этот выбор. Также решение, несмотря на некоторый boilerplate в описании каждой зависимости (опять же сравниваю с Cargo, где указывается только номер версии и название crate. Думаю здесь тоже возожмно было бы сократить, но это мелочь), помогает очень удобно организовывать версии библиотек, так что однозначно использовать нужно и следует вводить как best practice.


    1. GorovoyE Автор
      19.03.2024 10:02

      Спасибо за правки)

      Убрал из примеров ненужные зависимости (на самом деле, они стандартные, без них большая часть функционала работать не будет), оставил только на картинках, для примера, чтобы наглядней было как сейчас выглядит создание нового проекта.


  1. Rusrst
    19.03.2024 10:02

    Toml вроде уже раньше был автоматически создаваемым. Но вообще все это в now in Android посмотреть можно. Мне казалось все кто на KTS переезжали переводили проект на toml, т.к. это логично.