Сохраняйте данные в локальной базе данных, используя компонент Room из Android Jetpack .

Попробуйте Kotlin Multiplatform.
Kotlin Multiplatform позволяет использовать один и тот же слой базы данных с другими платформами. Узнайте, как настроить и работать с базой данных Room в KMP.

Приложения, обрабатывающие значительные объемы структурированных данных, могут получить большую выгоду от локального хранения этих данных. Наиболее распространенный вариант использования — кэширование важных фрагментов данных, чтобы пользователь мог просматривать контент в автономном режиме, даже если устройство не имеет доступа к сети.

Библиотека Room для работы с данными предоставляет уровень абстракции над SQLite, обеспечивая удобный доступ к базе данных и используя все возможности SQLite. В частности, Room предоставляет следующие преимущества:

  • Проверка SQL-запросов на этапе компиляции.
  • Удобные аннотации, которые минимизируют повторяющийся и подверженный ошибкам шаблонный код.
  • Упрощенные пути миграции баз данных.

Ввиду этих соображений мы настоятельно рекомендуем использовать Room вместо прямого использования API SQLite .

Настраивать

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

Котлин

dependencies {
    val room_version = "2.8.4"

    implementation("androidx.room:room-runtime:$room_version")

    // If this project uses any Kotlin source, use Kotlin Symbol Processing (KSP)
    // See Add the KSP plugin to your project
    ksp("androidx.room:room-compiler:$room_version")

    // If this project only uses Java source, use the Java annotationProcessor
    // No additional plugins are necessary
    annotationProcessor("androidx.room:room-compiler:$room_version")

    // optional - Kotlin Extensions and Coroutines support for Room
    implementation("androidx.room:room-ktx:$room_version")

    // optional - RxJava2 support for Room
    implementation("androidx.room:room-rxjava2:$room_version")

    // optional - RxJava3 support for Room
    implementation("androidx.room:room-rxjava3:$room_version")

    // optional - Guava support for Room, including Optional and ListenableFuture
    implementation("androidx.room:room-guava:$room_version")

    // optional - Test helpers
    testImplementation("androidx.room:room-testing:$room_version")

    // optional - Paging 3 Integration
    implementation("androidx.room:room-paging:$room_version")
}

Круто

dependencies {
    def room_version = "2.8.4"

    implementation "androidx.room:room-runtime:$room_version"

    // If this project uses any Kotlin source, use Kotlin Symbol Processing (KSP)
    // See KSP Quickstart to add KSP to your build
    ksp "androidx.room:room-compiler:$room_version"

    // If this project only uses Java source, use the Java annotationProcessor
    // No additional plugins are necessary
    annotationProcessor "androidx.room:room-compiler:$room_version"

    // optional - RxJava2 support for Room
    implementation "androidx.room:room-rxjava2:$room_version"

    // optional - RxJava3 support for Room
    implementation "androidx.room:room-rxjava3:$room_version"

    // optional - Guava support for Room, including Optional and ListenableFuture
    implementation "androidx.room:room-guava:$room_version"

    // optional - Test helpers
    testImplementation "androidx.room:room-testing:$room_version"

    // optional - Paging 3 Integration
    implementation "androidx.room:room-paging:$room_version"
}

Основные компоненты

В Room есть три основных компонента:

  • Класс базы данных , который содержит саму базу данных и служит основной точкой доступа для подключения к сохраненным данным вашего приложения.
  • Сущности данных , представляющие таблицы в базе данных вашего приложения.
  • Объекты доступа к данным (DAO) предоставляют методы, которые ваше приложение может использовать для запроса, обновления, вставки и удаления данных в базе данных.

Класс базы данных предоставляет вашему приложению экземпляры DAO, связанных с этой базой данных. В свою очередь, приложение может использовать DAO для извлечения данных из базы данных в виде экземпляров соответствующих объектов сущностей данных. Приложение также может использовать определенные сущности данных для обновления строк в соответствующих таблицах или для создания новых строк для вставки. На рисунке 1 показана взаимосвязь между различными компонентами Room.

Рисунок 1. Схема архитектуры библиотеки Room.

Пример реализации

В этом разделе представлен пример реализации базы данных Room с одной сущностью данных и одним DAO.

сущность данных

Приведенный ниже код определяет сущность данных User . Каждый экземпляр User представляет собой строку в таблице user в базе данных приложения.

Котлин

@Entity
data class User(
    @PrimaryKey val uid: Int,
    @ColumnInfo(name = "first_name") val firstName: String?,
    @ColumnInfo(name = "last_name") val lastName: String?
)

Java

@Entity
public class User {
    @PrimaryKey
    public int uid;

    @ColumnInfo(name = "first_name")
    public String firstName;

    @ColumnInfo(name = "last_name")
    public String lastName;
}

Чтобы узнать больше о сущностях данных в Room, см. раздел «Определение данных с помощью сущностей Room» .

Объект доступа к данным (DAO)

Приведённый ниже код определяет объект DAO под названием UserDao . UserDao предоставляет методы, которые остальная часть приложения использует для взаимодействия с данными в таблице user .

Котлин

@Dao
interface UserDao {
    @Query("SELECT * FROM user")
    fun getAll(): List<User>

    @Query("SELECT * FROM user WHERE uid IN (:userIds)")
    fun loadAllByIds(userIds: IntArray): List<User>

    @Query("SELECT * FROM user WHERE first_name LIKE :first AND " +
           "last_name LIKE :last LIMIT 1")
    fun findByName(first: String, last: String): User

    @Insert
    fun insertAll(vararg users: User)

    @Delete
    fun delete(user: User)
}

Java

@Dao
public interface UserDao {
    @Query("SELECT * FROM user")
    List<User> getAll();

    @Query("SELECT * FROM user WHERE uid IN (:userIds)")
    List<User> loadAllByIds(int[] userIds);

    @Query("SELECT * FROM user WHERE first_name LIKE :first AND " +
           "last_name LIKE :last LIMIT 1")
    User findByName(String first, String last);

    @Insert
    void insertAll(User... users);

    @Delete
    void delete(User user);
}

Чтобы узнать больше о DAO, см. раздел «Доступ к данным с помощью DAO в комнатах» .

База данных

Приведённый ниже код определяет класс AppDatabase для хранения базы данных. AppDatabase определяет конфигурацию базы данных и служит основной точкой доступа приложения к сохраняемым данным. Класс базы данных должен удовлетворять следующим условиям:

  • Класс должен быть аннотирован аннотацией @Database , которая включает массив entities , содержащий список всех сущностей данных, связанных с базой данных.
  • Класс должен быть абстрактным классом, наследующим RoomDatabase .
  • Для каждого класса DAO, связанного с базой данных, класс базы данных должен определить абстрактный метод, который не имеет аргументов и возвращает экземпляр класса DAO.

Котлин

@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

Java

@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
    public abstract UserDao userDao();
}

Примечание: Если ваше приложение работает в одном процессе, при создании экземпляра объекта AppDatabase следует придерживаться шаблона проектирования Singleton. Каждый экземпляр RoomDatabase довольно затратен, и вам редко требуется доступ к нескольким экземплярам в рамках одного процесса.

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

Использование

После определения сущности данных, объекта DAO и объекта базы данных, вы можете использовать следующий код для создания экземпляра базы данных:

Котлин

val db = Room.databaseBuilder(
            applicationContext,
            AppDatabase::class.java, "database-name"
        ).build()

Java

AppDatabase db = Room.databaseBuilder(getApplicationContext(),
        AppDatabase.class, "database-name").build();

Затем вы можете использовать абстрактные методы из AppDatabase , чтобы получить экземпляр DAO. В свою очередь, вы можете использовать методы экземпляра DAO для взаимодействия с базой данных:

Котлин

val userDao = db.userDao()
val users: List<User> = userDao.getAll()

Java

UserDao userDao = db.userDao();
List<User> users = userDao.getAll();

Дополнительные ресурсы

Чтобы узнать больше о Room, ознакомьтесь со следующими дополнительными ресурсами:

Образцы

Кодлабс

Блоги