Основы Cloud Firestore
Читайте и записывайте данные в реальном времени
«Основы Cloud Firestore» — бесплатный урок Android Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Android Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Android Academy содержит 4 уроков всего.
Что такое Cloud Firestore?
Cloud Firestore — это гибкая и масштабируемая база данных NoSQL от Firebase. Она хранит данные в виде документов, объединённых в коллекции.
- Документ — это набор полей «ключ/значение», например объект JSON.
- Коллекция — контейнер для документов.
- Документы могут содержать подколлекции, образуя дерево.
Firestore также поддерживает обновления в реальном времени и изначально работает офлайн.
Получение экземпляра Firestore
Получите доступ к базе данных через Firebase.firestore. Затем с помощью collection("name") можно обратиться к коллекции, а с помощью document("id") — к определённому документу.
Ссылки создаются без больших затрат — они описывают расположение, а не сами данные.
import com.google.firebase.Firebase
import com.google.firebase.firestore.firestore
val db = Firebase.firestore
val usersRef = db.collection("users")
val oneUser = db.collection("users").document("abc123")Моделирование данных
Firestore удобно сопоставляется с классами данных Kotlin. Каждое свойство становится полем документа.
Добавьте конструктор без аргументов (для этого достаточно значений по умолчанию), чтобы Firestore мог десериализовать документы обратно в объекты.
data class Note(
val title: String = "",
val body: String = "",
val done: Boolean = false,
val createdAt: Long = 0L
)Запись документа
Используйте set, чтобы создать документ или перезаписать его. Позвольте Firestore сгенерировать идентификатор с помощью add либо выберите собственный идентификатор с помощью document(id).set(...).
Эти вызовы возвращают задачи; в сопрограммах их можно обработать с помощью await().
import com.google.firebase.Firebase
import com.google.firebase.firestore.firestore
import kotlinx.coroutines.tasks.await
suspend fun addNote(note: Note): String {
val ref = Firebase.firestore
.collection("notes")
.add(note) // auto-generated ID
.await()
return ref.id
}Чтение документа
get() один раз загружает документ. Преобразуйте его в свой класс данных с помощью toObject(Note::class.java).
Всегда проверяйте exists() — ссылка на отсутствующий документ возвращает снимок, который просто не существует.
import com.google.firebase.Firebase
import com.google.firebase.firestore.firestore
import kotlinx.coroutines.tasks.await
suspend fun loadNote(id: String): Note? {
val snapshot = Firebase.firestore
.collection("notes")
.document(id)
.get()
.await()
return if (snapshot.exists()) snapshot.toObject(Note::class.java) else null
}Обновление и удаление
update изменяет определённые поля, не затрагивая остальные данные документа. delete полностью удаляет документ.
Используйте set(..., SetOptions.merge()), если хотите выполнить частичную запись, которая также создаст документ, если он отсутствует.
import com.google.firebase.Firebase
import com.google.firebase.firestore.firestore
import kotlinx.coroutines.tasks.await
suspend fun markDone(id: String) {
Firebase.firestore.collection("notes").document(id)
.update("done", true)
.await()
}
suspend fun removeNote(id: String) {
Firebase.firestore.collection("notes").document(id)
.delete()
.await()
}Запрос коллекции
Создавайте запросы, объединяя фильтры: whereEqualTo, whereGreaterThan, orderBy, limit и другие.
Запрос возвращает QuerySnapshot; переберите его документы и преобразуйте каждый в свою модель.
import com.google.firebase.Firebase
import com.google.firebase.firestore.firestore
import kotlinx.coroutines.tasks.await
suspend fun pendingNotes(): List<Note> {
val snap = Firebase.firestore.collection("notes")
.whereEqualTo("done", false)
.orderBy("createdAt")
.limit(20)
.get()
.await()
return snap.documents.mapNotNull { it.toObject(Note::class.java) }
}Слушатели данных в реальном времени
Главное преимущество Firestore — работа в реальном времени. addSnapshotListener сразу передаёт текущие данные, а затем автоматически отправляет каждое изменение.
Функция возвращает ListenerRegistration — вызовите remove(), когда закончите работу, чтобы прекратить получение обновлений.
import com.google.firebase.Firebase
import com.google.firebase.firestore.firestore
val registration = Firebase.firestore.collection("notes")
.whereEqualTo("done", false)
.addSnapshotListener { snapshot, error ->
if (error != null || snapshot == null) return@addSnapshotListener
val notes = snapshot.toObjects(Note::class.java)
println("Now have ${notes.size} pending notes")
}
// Later: registration.remove()Данные реального времени как Flow
В Compose принято предоставлять данные Firestore в виде Kotlin Flow. callbackFlow связывает обратный вызов слушателя с потоком, а awaitClose удаляет слушатель, когда сбор данных прекращается.
import com.google.firebase.Firebase
import com.google.firebase.firestore.firestore
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
fun notesFlow(): Flow<List<Note>> = callbackFlow {
val reg = Firebase.firestore.collection("notes")
.addSnapshotListener { snap, err ->
if (err == null && snap != null) {
trySend(snap.toObjects(Note::class.java))
}
}
awaitClose { reg.remove() }
}Отображение данных в Compose
Собирайте поток с помощью collectAsStateWithLifecycle() и отображайте его в LazyColumn. Список обновляется сам при каждом изменении Firestore — вручную обновлять его не нужно.
@Composable
fun NotesScreen(viewModel: NotesViewModel) {
val notes by viewModel.notes.collectAsStateWithLifecycle()
LazyColumn {
items(notes) { note ->
ListItem(
headlineContent = { Text(note.title) },
supportingContent = { Text(note.body) }
)
}
}
}Правила безопасности важны
По умолчанию Firestore закрыт для доступа. Правила безопасности определяют, кто может читать или записывать данные по каждому пути — они выполняются на сервере, и клиент не может их обойти.
Распространённое правило: пользователь может обращаться только к собственным данным, ключом которых служит его uid аутентификации.
// firestore.rules
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId}/{document=**} {
allow read, write: if request.auth != null
&& request.auth.uid == userId;
}
}
}Быстрая проверка
Вы хотите, чтобы список Compose мгновенно обновлялся при любом изменении исходных данных Firestore, без ручного обновления. Какой API следует использовать?
Итоги: Firestore
Теперь вы умеете хранить и синхронизировать данные с помощью Cloud Firestore:
- Данные хранятся как документы в коллекциях; представляйте их с помощью классов данных Kotlin.
- Записывайте данные через
add/set, читайте черезget, изменяйте черезupdate/delete. - Создавайте запросы с помощью
whereEqualTo,orderBy,limit. - Используйте
addSnapshotListener(илиcallbackFlow) для интерфейса в реальном времени. - Защищайте данные с помощью правил безопасности, использующих
request.auth.uid.
Далее: обращение к пользователям, когда приложение закрыто, с помощью Cloud Messaging.
Часто задаваемые вопросы
Урок «Основы Cloud Firestore» бесплатный?
Да — полный текст урока «Основы Cloud Firestore» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Android Academy, подпишись на CoddyKit PRO. Курс Android Academy содержит 4 уроков всего.
Чему я научусь в уроке «Основы Cloud Firestore»?
Читайте и записывайте данные в реальном времени Ты практикуешь Android Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Android Academy?
Предыдущий опыт не требуется. Android Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Основы Cloud Firestore»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Android Academy?
Да. Каждый урок Android Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Настройка Firebase
- Аутентификация Firebase
- Основы Cloud Firestore
- Отправка уведомлений через Cloud Messaging