1. Введение
Последнее обновление: 16.11.2022
Разработка Android-приложения с использованием Firebase и Jetpack Compose.
В этом практическом занятии вы создадите Android-приложение под названием Make It So. Пользовательский интерфейс этого приложения полностью построен с помощью Jetpack Compose , современного инструментария Android для создания нативных пользовательских интерфейсов — он интуитивно понятен и требует меньше кода, чем написание XML-файлов и их привязка к Activity, Fragment или View.
Первый шаг к пониманию того, насколько хорошо Firebase и Jetpack Compose работают вместе, — это понимание современной архитектуры Android. Хорошая архитектура делает систему простой для понимания, разработки и сопровождения, поскольку она четко показывает, как компоненты организованы и взаимодействуют друг с другом. В мире Android рекомендуемая архитектура называется Model - View - ViewModel . Model представляет собой слой, который обращается к данным в приложении. View — это слой пользовательского интерфейса, и он не должен знать ничего о бизнес-логике. А ViewModel — это место, где применяется бизнес-логика, которая иногда требует, чтобы ViewModel обращался к слою Model .
Мы настоятельно рекомендуем прочитать эту статью , чтобы понять, как применяется модель - представление - ViewModel в Android-приложении, созданном с помощью Jetpack Compose, поскольку это упростит понимание кода и выполнение последующих шагов.
Что вы построите
Make It So — это простое приложение для составления списков дел, позволяющее пользователю добавлять и редактировать задачи, устанавливать флажки, приоритеты и сроки выполнения, а также отмечать задачи как выполненные. На изображениях ниже показаны две основные страницы этого приложения: страница создания задачи и главная страница со списком созданных задач.


Вы добавите некоторые функции, которых нет в этом приложении:
- Аутентификация пользователей с помощью электронной почты и пароля.
- Добавьте обработчик событий к коллекции Firestore и настройте пользовательский интерфейс на реагирование на изменения.
- Добавьте пользовательские трассировки для мониторинга производительности конкретного кода в приложении.
- Создайте переключатель функций с помощью удаленной конфигурации и используйте поэтапное развертывание для его запуска.
Что вы узнаете
- Как использовать аутентификацию Firebase, мониторинг производительности, удаленную конфигурацию и Cloud Firestore в современном Android-приложении
- Как интегрировать API Firebase в архитектуру MVVM
- Как отобразить изменения, внесенные с помощью API Firebase, в пользовательском интерфейсе Compose.
Что вам понадобится
- Android Studio Flamingo+
- Эмулятор Android с API 21 или выше
- Знание языка программирования Kotlin.
2. Загрузите демонстрационное приложение и настройте Firebase.
Получите код демонстрационного приложения.
Клонируйте репозиторий GitHub из командной строки:
git clone https://github.com/FirebaseExtended/make-it-so-android.git
Создайте проект Firebase.
- Войдите в консоль Firebase, используя свою учетную запись Google.
- Нажмите кнопку, чтобы создать новый проект, а затем введите название проекта (например,
Compose Firebase codelab). - Нажмите «Продолжить» .
- Если появится запрос, ознакомьтесь с условиями использования Firebase и примите их, после чего нажмите «Продолжить» .
- (Необязательно) Включите помощь ИИ в консоли Firebase (в Firebase она называется "Gemini").
- Для выполнения этого практического задания вам потребуется Google Analytics для использования расширенных параметров таргетинга с помощью функции удаленной настройки, поэтому оставьте переключатель для параметра Google Analytics включенным . Следуйте инструкциям на экране, чтобы настроить Google Analytics.
- Нажмите «Создать проект» , дождитесь завершения подготовки проекта, а затем нажмите «Продолжить» .
Добавьте Android-приложение в свой проект Firebase.
В вашем проекте Firebase вы можете зарегистрировать различные приложения: для Android, iOS, веб-приложений, Flutter и Unity.
Выберите вариант для Android, как показано здесь:

Затем выполните следующие шаги:
- Введите
com.example.makeitsoв качестве имени пакета и, при желании, укажите псевдоним. Для этого практического задания добавлять сертификат подписи отладки не требуется. - Нажмите «Далее» , чтобы зарегистрировать приложение и получить доступ к файлу конфигурации Firebase.
- Нажмите «Скачать google-services.json» , чтобы загрузить файл конфигурации и сохранить его в каталоге
make-it-so-android/app. - Нажмите «Далее» . Поскольку SDK Firebase уже включены в файл
build.gradleв примере проекта, нажмите «Далее» , чтобы перейти к следующим шагам . - Нажмите «Продолжить» в консоли , чтобы завершить.
Для корректной работы приложения Make it So необходимо выполнить два действия в консоли, прежде чем переходить к коду: включить поставщиков аутентификации и создать базу данных Firestore.
Настройка аутентификации
Для начала давайте включим аутентификацию, чтобы пользователи могли входить в приложение:
- В меню «Создание» выберите «Аутентификация» , а затем нажмите «Начать» .
- В карточке «Способ входа» выберите «Электронная почта/Пароль» и включите эту опцию.
- Далее нажмите «Добавить нового поставщика услуг» , выберите и включите анонимный режим .
Настройка Cloud Firestore
Далее настройте Firestore. Вы будете использовать Firestore для хранения задач авторизованного пользователя. Каждый пользователь получит свой собственный документ в коллекции базы данных.
- В левой панели консоли Firebase разверните раздел «Сборка» , а затем выберите базу данных Firestore .
- Нажмите «Создать базу данных» .
- Оставьте значение параметра " Идентификатор базы данных" равным
(default). - Выберите местоположение для вашей базы данных, затем нажмите «Далее» .
Для создания настоящего приложения вам следует выбрать местоположение, расположенное недалеко от ваших пользователей. - Нажмите «Пуск» в тестовом режиме . Ознакомьтесь с отказом от ответственности в отношении правил безопасности.
На следующих шагах этого раздела вы добавите правила безопасности для защиты ваших данных. Не распространяйте и не предоставляйте доступ к приложению публично, не добавив правила безопасности для вашей базы данных. - Нажмите «Создать» .
Давайте уделим немного времени созданию надежных правил безопасности для базы данных Firestore.
- Откройте панель управления Firestore и перейдите на вкладку «Правила» .
- Обновите правила безопасности следующим образом:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /tasks/{document} {
allow create: if request.auth != null;
allow read, update, delete: if request.auth != null
&& resource.data.userId == request.auth.uid
&& request.data.userId == resource.data.userId;
}
}
}
Эти правила, по сути, гласят, что любой авторизованный пользователь приложения может создать для себя документ в любой коллекции. Затем, после создания документа, только пользователь, создавший этот документ, сможет просматривать, обновлять или удалять его.
Запустите приложение
Теперь вы готовы запустить приложение! Откройте папку make-it-so-android/start в Android Studio и запустите приложение (это можно сделать с помощью эмулятора Android или реального устройства Android).
3. Аутентификация Firebase
Какую функцию вы собираетесь добавить?
В текущей версии демонстрационного приложения Make It So пользователь может начать использовать приложение без предварительного входа в систему. Для этого используется анонимная аутентификация. Однако анонимные учетные записи не позволяют пользователю получать доступ к своим данным на других устройствах или даже в будущих сессиях. Хотя анонимная аутентификация полезна для «теплого» знакомства с приложением, всегда следует предоставлять пользователям возможность перейти на другой способ входа. С учетом этого, в этом практическом задании вы добавите в приложение Make It So аутентификацию по электронной почте и паролю.
Пора программировать!
Как только пользователь создаст учетную запись, введя адрес электронной почты и пароль, вам необходимо запросить у API аутентификации Firebase учетные данные электронной почты, а затем связать новые учетные данные с анонимной учетной записью. Откройте файл AccountServiceImpl.kt в Android Studio и обновите функцию linkAccount следующим образом:
model/service/impl/AccountServiceImpl.kt
override suspend fun linkAccount(email: String, password: String) {
val credential = EmailAuthProvider.getCredential(email, password)
auth.currentUser!!.linkWithCredential(credential).await()
}
Теперь откройте файл SignUpViewModel.kt и вызовите функцию linkAccount сервиса внутри блока launchCatching функции onSignUpClick :
screens/sign_up/SignUpViewModel.kt
launchCatching {
accountService.linkAccount(email, password)
openAndPopUp(SETTINGS_SCREEN, SIGN_UP_SCREEN)
}
Сначала выполняется попытка аутентификации, и если вызов проходит успешно, происходит переход к следующему экрану (экрану SettingsScreen ). Поскольку эти вызовы выполняются внутри блока launchCatching , если на первой строке возникнет ошибка, исключение будет перехвачено и обработано, и вторая строка вообще не будет достигнута.
Как только снова откроется SettingsScreen , необходимо убедиться, что параметры «Войти» и «Создать учетную запись» исчезли, поскольку пользователь уже аутентифицирован. Для этого настроим SettingsViewModel на отслеживание статуса текущего пользователя (доступно в AccountService.kt ), чтобы проверить, является ли учетная запись анонимной или нет. Для этого обновите uiState в SettingsViewModel.kt следующим образом:
screens/settings/SettingsViewModel.kt
val uiState = accountService.currentUser.map {
SettingsUiState(it.isAnonymous)
}
Последнее, что вам нужно сделать, это обновить uiState в SettingsScreen.kt , чтобы он собирал состояния, передаваемые SettingsViewModel :
screens/settings/SettingsScreen.kt
val uiState by viewModel.uiState.collectAsState(
initial = SettingsUiState(false)
)
Теперь при каждом изменении пользователя SettingsScreen будет перестраиваться, отображая параметры в соответствии с новым состоянием аутентификации пользователя.
Пора тестировать!
Запустите Make it So и перейдите в настройки, нажав на значок шестеренки в правом верхнем углу экрана. Там нажмите на опцию «Создать учетную запись»:


Введите действительный адрес электронной почты и надежный пароль для создания учетной записи. После этого вы должны перейти на страницу настроек, где увидите две новые опции: выход из учетной записи и ее удаление. Проверить созданную учетную запись можно на панели управления аутентификацией в консоли Firebase, перейдя на вкладку «Пользователи».
4. Cloud Firestore
Какую функцию вы собираетесь добавить?
Для Cloud Firestore вам потребуется добавить слушатель в коллекцию Firestore, которая хранит документы, представляющие задачи, отображаемые в Make it So. После добавления этого слушателя вы будете получать все обновления, внесенные в эту коллекцию.
Пора программировать!
Обновите Flow доступный в StorageServiceImpl.kt , следующим образом:
model/service/impl/StorageServiceImpl.kt
override val tasks: Flow<List<Task>>
get() =
auth.currentUser.flatMapLatest { user ->
firestore.collection(TASK_COLLECTION).whereEqualTo(USER_ID_FIELD, user.id).dataObjects()
}
Этот код добавляет обработчик событий к коллекции задач на основе user.id Каждая задача представлена документом в коллекции с именем tasks , и каждая из них имеет поле с именем userId . Обратите внимание, что новый Flow будет сгенерирован, если статус currentUser изменится (например, при выходе из системы).
Теперь вам нужно настроить Flow в файле TasksViewModel.kt так, чтобы он соответствовал потоку в сервисе:
screens/tasks/TasksViewModel.kt
val tasks = storageService.tasks
И последнее, что нужно сделать, это заставить composable function в файле TasksScreens.kt , которая представляет пользовательский интерфейс, отслеживать этот поток и собирать его как состояние. Каждый раз, когда состояние изменяется, компонуемая функция будет автоматически перестраиваться и отображать пользователю самое последнее состояние. Добавьте это в TasksScreen composable function :
screens/tasks/TasksScreen.kt
val tasks = viewModel
.tasks
.collectAsStateWithLifecycle(emptyList())
Как только компонуемая функция получит доступ к этим состояниям, вы можете обновить LazyColumn (структуру, используемую для отображения списка на экране) следующим образом:
screens/tasks/TasksScreen.kt
LazyColumn {
items(tasks.value, key = { it.id }) { taskItem ->
TaskItem( [...] )
}
}
Пора тестировать!
Чтобы проверить работоспособность, добавьте новую задачу с помощью приложения (нажав кнопку «Добавить» в правом нижнем углу экрана). После создания задачи она должна появиться в коллекции Firestore в консоли Firestore. Если вы войдете в Make it So на других устройствах с той же учетной записью, вы сможете редактировать свои задачи и наблюдать за их обновлением на всех устройствах в режиме реального времени.
5. Мониторинг производительности
Какую функцию вы собираетесь добавить?
Производительность — очень важный параметр, на который следует обращать внимание, поскольку пользователи с большой вероятностью откажутся от использования вашего приложения, если его производительность низкая и выполнение простых задач занимает слишком много времени. Именно поэтому иногда полезно собирать метрики о конкретном пути пользователя в вашем приложении. И чтобы помочь вам в этом, Firebase Performance Monitoring предлагает пользовательские трассировки . Следуйте приведенным ниже шагам, чтобы добавить пользовательские трассировки и измерить производительность в различных фрагментах кода в Make it So.
Пора программировать!
Если вы откроете файл Performance.kt , вы увидите встроенную функцию с именем trace. Эта функция вызывает API мониторинга производительности для создания пользовательской трассировки, передавая имя трассировки в качестве параметра. Другой параметр, который вы увидите, — это блок кода, который вы хотите отслеживать. По умолчанию для каждой трассировки собирается метрика времени, необходимого для полного выполнения:
model/service/Performance.kt
inline fun <T> trace(name: String, block: Trace.() -> T): T = Trace.create(name).trace(block)
Вы можете выбрать, какие части кода, по вашему мнению, важно измерить, и добавить к ним пользовательские трассировки. Вот пример добавления пользовательской трассировки к функции linkAccount , которую вы видели ранее (в AccountServiceImpl.kt ) в этом практическом задании:
model/service/impl/AccountServiceImpl.kt
override suspend fun linkAccount(email: String, password: String): Unit =
trace(LINK_ACCOUNT_TRACE) {
val credential = EmailAuthProvider.getCredential(email, password)
auth.currentUser!!.linkWithCredential(credential).await()
}
Теперь ваша очередь! Добавьте несколько пользовательских трассировок в приложение Make it So и перейдите к следующему разделу, чтобы проверить, работает ли оно должным образом.
Пора тестировать!
После добавления пользовательских трассировок запустите приложение и убедитесь, что несколько раз использовали функции, которые хотите измерить. Затем перейдите в консоль Firebase и откройте панель мониторинга производительности . В нижней части экрана вы найдете три вкладки: «Сетевые запросы» , «Пользовательские трассировки» и «Отображение экрана» .
Перейдите на вкладку «Пользовательские трассировки» и убедитесь, что добавленные вами в код трассировки отображаются там, а также что вы можете увидеть, сколько времени обычно требуется для выполнения этих фрагментов кода.
6. Удалённая настройка
Какую функцию вы собираетесь добавить?
У функции Remote Config множество вариантов применения: от удалённого изменения внешнего вида приложения до настройки различного поведения для разных сегментов пользователей. В этом практическом занятии вы используете Remote Config для создания переключателя функций, который будет отображать или скрывать новую функцию редактирования задач в приложении Make it So.
Пора программировать!
Первое, что вам нужно сделать, это создать конфигурацию в консоли Firebase. Для этого перейдите на панель управления Remote Config и нажмите кнопку «Добавить параметр» . Заполните поля в соответствии с изображением ниже:

После заполнения всех полей нажмите кнопку «Сохранить» , а затем «Опубликовать» . Теперь, когда параметр создан и доступен в вашем коде, вам необходимо добавить в приложение код, который будет получать новые значения. Откройте файл ConfigurationServiceImpl.kt и обновите реализацию следующих двух функций:
model/service/impl/ConfigurationServiceImpl.kt
override suspend fun fetchConfiguration(): Boolean {
return remoteConfig.fetchAndActivate().await()
}
override val isShowTaskEditButtonConfig: Boolean
get() = remoteConfig[SHOW_TASK_EDIT_BUTTON_KEY].asBoolean()
Первая функция получает значения с сервера и вызывается сразу после запуска приложения, в файле SplashViewModel.kt . Это лучший способ гарантировать, что самые актуальные значения будут доступны на всех экранах с самого начала. Изменение пользовательского интерфейса или поведения приложения позже, когда пользователь занят другими делами, — это плохой пользовательский опыт!
Вторая функция возвращает логическое значение, опубликованное для параметра, который вы только что создали в консоли. Вам потребуется получить эту информацию в TasksViewModel.kt , добавив следующее в функцию loadTaskOptions :
screens/tasks/TasksViewModel.kt
fun loadTaskOptions() {
val hasEditOption = configurationService.isShowTaskEditButtonConfig
options.value = TaskActionOption.getOptions(hasEditOption)
}
Вы получаете значение из первой строки и используете его для загрузки пунктов меню для элементов задачи во второй строке. Если значение равно false , это означает, что меню не будет содержать опцию редактирования. Теперь, когда у вас есть список опций, вам нужно правильно отобразить их в пользовательском интерфейсе. Поскольку вы создаете приложение с помощью Jetpack Compose, вам нужно найти composable function , которая определяет, как должен выглядеть пользовательский интерфейс TasksScreen . Поэтому откройте файл TasksScreen.kt и обновите LazyColum , чтобы он указывал на параметры, доступные в TasksViewModel.kt :
screens/tasks/TasksScreen.kt
val options by viewModel.options
LazyColumn {
items(tasks.value, key = { it.id }) { taskItem ->
TaskItem(
options = options,
[...]
)
}
}
TaskItem — это ещё одна composable function , которая определяет внешний вид пользовательского интерфейса отдельной задачи. Каждая задача имеет меню с опциями, которое отображается, когда пользователь щёлкает по значку с тремя точками в конце меню.
Пора тестировать!
Теперь вы готовы запустить приложение! Убедитесь, что значение, опубликованное вами через консоль Firebase, соответствует поведению приложения:
- Если это
false, при нажатии на значок с тремя точками вы должны увидеть только два варианта; - Если это
true, то при нажатии на значок с тремя точками вы должны увидеть три варианта;
Попробуйте несколько раз изменить значение в консоли и перезапустить приложение. Вот как легко запускать новые функции в вашем приложении с помощью удаленной конфигурации!
7. Поздравляем!
Поздравляем, вы успешно создали Android-приложение с помощью Firebase и Jetpack Compose!
Вы добавили аутентификацию Firebase, мониторинг производительности, удаленную конфигурацию и Cloud Firestore в Android-приложение, полностью созданное с использованием Jetpack Compose для пользовательского интерфейса, и адаптировали его к рекомендуемой архитектуре MVVM!
Дополнительная информация
- Разработка Android-приложения с использованием Firebase и Compose.
- Добавление аутентификации Firebase в приложение Jetpack Compose
- Добавление Cloud Firestore в приложение Jetpack Compose
- Добавление сопрограмм и Flow в Android-приложение, созданное с помощью Firebase и Compose.
- Добавление мониторинга производительности Firebase в приложение Jetpack Compose
- Добавление Firebase Remote Config в приложение Jetpack Compose