1. Введение
Последнее обновление: 16.11.2022
Создание приложения для Android с помощью Firebase и Jetpack Compose
В этой лабораторной работе вы создадите приложение для Android под названием Make It So. Пользовательский интерфейс этого приложения полностью создан с помощью Jetpack Compose — современного инструментария Android для создания нативного пользовательского интерфейса. Он интуитивно понятен и требует меньше кода, чем при написании XML-файлов и их привязке к Activity, Fragments или View.
Первый шаг к пониманию того, насколько хорошо Firebase и Jetpack Compose работают вместе, — это понимание современной архитектуры Android. Хорошая архитектура делает систему простой для понимания, разработки и поддержки, поскольку она наглядно демонстрирует организацию и взаимодействие компонентов. В мире Android рекомендуемая архитектура называется Model-View-ViewModel . Model представляет собой уровень доступа к данным в приложении. View — это уровень пользовательского интерфейса, который не должен ничего знать о бизнес-логике. А ViewModel — это место, где применяется бизнес-логика, что иногда требует от ViewModel вызова уровня Model .
Мы настоятельно рекомендуем прочитать эту статью , чтобы понять, как Model - View - ViewModel применяется к приложению Android, созданному с помощью Jetpack Compose, поскольку это упростит понимание кодовой базы и выполнение последующих шагов.
Что вы построите
Make It So — это простое приложение для управления списками дел, которое позволяет добавлять и редактировать задачи, устанавливать флаги, приоритеты и сроки выполнения, а также отмечать выполненные задачи. На изображениях ниже показаны две основные страницы приложения: страница создания задач и главная страница со списком созданных задач.
Вы добавите некоторые функции, которых нет в этом приложении:
- Аутентификация пользователей с помощью электронной почты и пароля
- Добавьте прослушиватель в коллекцию Firestore и заставьте пользовательский интерфейс реагировать на изменения.
- Добавляйте пользовательские трассировки для мониторинга производительности определенного кода в приложении.
- Создайте переключатель функций с помощью Remote Config и используйте поэтапное развертывание для его запуска.
Чему вы научитесь
- Как использовать аутентификацию 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 (так называемая «Gemini в Firebase»).
- Для этой практической работы вам понадобится Google Analytics для использования расширенных параметров таргетинга с Remote Config, поэтому оставьте переключатель Google Analytics включённым . Следуйте инструкциям на экране, чтобы настроить Google Analytics.
- Нажмите «Создать проект» , дождитесь завершения подготовки проекта, а затем нажмите «Продолжить» .
Добавьте приложение Android в свой проект Firebase
В вашем проекте Firebase вы можете зарегистрировать различные приложения: для Android, iOS, Web, Flutter и Unity.
Выберите вариант Android, как показано здесь:
Затем выполните следующие действия:
- Введите
com.example.makeitso
в качестве имени пакета и, при желании, псевдоним. Для этой лабораторной работы вам не нужно добавлять сертификат отладочной подписи. - Нажмите «Далее» , чтобы зарегистрировать приложение и получить доступ к файлу конфигурации Firebase.
- Нажмите «Загрузить google-services.json» , чтобы загрузить файл конфигурации и сохранить его в каталоге
make-it-so-android/app
. - Нажмите «Далее» . Поскольку пакеты Firebase SDK уже включены в файл
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 вам нужно будет добавить прослушиватель в коллекцию 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
. Обратите внимание, что при изменении статуса currentUser
(например, при выходе из системы) будет запущен новый Flow
.
Теперь вам нужно сделать так, чтобы Flow
в TasksViewModel.kt
отражал то же самое, что и в сервисе:
screens/tasks/TasksViewModel.kt
val tasks = storageService.tasks
И последнее, что нужно сделать, — это заставить composable function
в TasksScreens.kt
, представляющую пользовательский интерфейс, отслеживать этот поток и собирать его как состояние. Каждый раз при изменении состояния компонуемая функция будет автоматически перекомпоновываться и отображать пользователю последнее состояние. Добавьте это в TasksScreen composable function
:
экраны/задачи/TasksScreen.kt
val tasks = viewModel
.tasks
.collectAsStateWithLifecycle(emptyList())
Как только компонуемая функция получит доступ к этим состояниям, вы можете обновить LazyColumn
(структуру, используемую для отображения списка на экране), чтобы она выглядела следующим образом:
экраны/задачи/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 мониторинга производительности для создания пользовательской трассировки, передавая имя трассировки в качестве параметра. Другой параметр — это блок кода, который вы хотите отслеживать. Метрика по умолчанию, собираемая для каждой трассировки, — это время, необходимое для её полного выполнения:
модель/сервис/Производительность.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
:
экраны/задачи/TasksScreen.kt
val options by viewModel.options
LazyColumn {
items(tasks.value, key = { it.id }) { taskItem ->
TaskItem(
options = options,
[...]
)
}
}
TaskItem
— ещё одна composable function
, которая определяет, как должен выглядеть пользовательский интерфейс отдельной задачи. У каждой задачи есть меню с опциями, которое отображается при нажатии пользователем на значок с тремя точками в конце задачи.
Время проверить!
Теперь вы готовы к запуску приложения! Убедитесь, что значение, опубликованное вами с помощью консоли Firebase, соответствует поведению приложения:
- Если значение равно
false
, при нажатии на значок с тремя точками вы увидите только два варианта: - Если это
true
, то при нажатии на значок с тремя точками вы увидите три варианта:
Попробуйте изменить значение несколько раз в консоли и перезапустить приложение. Вот так просто запускать новые функции в приложении с помощью Remote Config!
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