Создайте приложение для Android с помощью Firebase и Jetpack Compose.

1. Введение

Последнее обновление: 16 ноября 2022 г.

Создание приложения для Android с помощью Firebase и Jetpack Compose

В этой лаборатории кода вы создадите приложение для Android под названием Make It So. Пользовательский интерфейс этого приложения полностью создан с помощью Jetpack Compose , современного набора инструментов Android для создания собственного пользовательского интерфейса. Он интуитивно понятен и требует меньше кода, чем написание XML-файлов и их привязка к действиям, фрагментам или представлениям.

Первый шаг к пониманию того, насколько хорошо Firebase и Jetpack Compose работают вместе, — это понимание современной архитектуры Android. Хорошая архитектура делает систему простой для понимания, разработки и обслуживания, поскольку она делает очень понятным, как компоненты организованы и взаимодействуют друг с другом. В мире Android рекомендуемая архитектура называется Model — View — ViewModel . Модель представляет собой уровень, который обращается к данным в приложении. Представление — это уровень пользовательского интерфейса, который ничего не должен знать о бизнес-логике. А ViewModel — это место, где применяется бизнес-логика, что иногда требует, чтобы ViewModel вызывал уровень модели .

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

Что ты построишь

Make It So — это простое приложение со списком дел, которое позволяет пользователю добавлять и редактировать задачи, добавлять флаги, приоритеты и сроки выполнения, а также отмечать задачи как выполненные. На изображениях ниже показаны две основные страницы этого приложения: страница создания задачи и главная страница со списком созданных задач.

Сделайте это так Экран добавления задачиСделайте это так Главный экран

Вы добавите некоторые функции, которых нет в этом приложении:

  • Аутентификация пользователей с помощью электронной почты и пароля
  • Добавьте прослушиватель в коллекцию Firestore и заставьте пользовательский интерфейс реагировать на изменения.
  • Добавляйте пользовательские трассировки для мониторинга производительности определенного кода в приложении.
  • Создайте переключатель функций с помощью Remote Config и используйте поэтапное развертывание для его запуска.

Что вы узнаете

  • Как использовать аутентификацию Firebase, мониторинг производительности, удаленную настройку и Cloud Firestore в современном приложении для Android
  • Как вписать API Firebase в архитектуру MVVM
  • Как отразить изменения, внесенные с помощью API Firebase, в пользовательском интерфейсе Compose

Что вам понадобится

2. Получите образец приложения и настройте Firebase.

Получите код примера приложения

Клонируйте репозиторий GitHub из командной строки:

git clone https://github.com/FirebaseExtended/make-it-so-android.git

Настройте Firebase

Первое, что вам нужно сделать, это зайти в консоль Firebase и создать проект Firebase, нажав кнопку «+ Добавить проект», как вы можете видеть ниже:

Консоль Firebase

Следуйте инструкциям на экране, чтобы завершить создание проекта.

Внутри каждого проекта Firebase вы можете создавать разные приложения: для Android, iOS, Web, Flutter и Unity. Выберите вариант Android, как вы видите здесь:

Обзор проекта Firebase

Затем выполните следующие действия:

  1. Введите com.example.makeitso в качестве имени пакета и, при необходимости, введите псевдоним. Для этой лаборатории кода вам не нужно добавлять сертификат подписи отладки.
  2. Нажмите «Далее» , чтобы зарегистрировать свое приложение и получить доступ к файлу конфигурации Firebase.
  3. Нажмите «Загрузить google-services.json» , чтобы загрузить файл конфигурации и сохранить его в каталоге make-it-so-android/app .
  4. Нажмите Далее . Поскольку SDK Firebase уже включены в файл build.gradle в примере проекта, нажмите «Далее» , чтобы перейти к следующим шагам .
  5. Нажмите Продолжить на консоли , чтобы завершить.

Чтобы приложение Make it So работало правильно, вам нужно сделать в консоли две вещи, прежде чем переходить к коду: включить поставщиков аутентификации и создать базу данных Firestore. Сначала давайте включим аутентификацию, чтобы пользователи могли войти в приложение:

  1. В меню «Создать» выберите «Аутентификация» , а затем нажмите «Начать» .
  2. На карточке «Способ входа» выберите «Электронная почта/пароль» и включите его.
  3. Затем нажмите «Добавить нового поставщика» , выберите и включите «Анонимный» .

Далее настройте Firestore. Вы будете использовать Firestore для хранения задач вошедшего пользователя. Каждый пользователь получит свой собственный документ в коллекции базы данных.

  1. В меню «Создать» выберите Firestore , затем нажмите «Создать базу данных» .
  2. Оставьте включенным «Пуск в рабочем режиме» и нажмите «Далее» .
  3. При появлении запроса выберите место, где будут храниться данные вашего Cloud Firestore. При разработке рабочего приложения вам нужно, чтобы оно находилось в регионе, близком к большинству ваших пользователей, и было общим с другими сервисами Firebase, такими как Функции. Для этой лаборатории кода вы можете сохранить регион по умолчанию или выбрать ближайший к вам регион.
  4. Нажмите «Включить» , чтобы подготовить базу данных Firestore.

Давайте потратим немного времени на создание надежных правил безопасности для базы данных Firestore. Откройте панель управления Firestore и перейдите на вкладку «Правила» . Затем обновите Правила безопасности, чтобы они выглядели следующим образом:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow create: if request.auth != null;
      allow read, update, delete: if request.auth != null && resource.data.userId == request.auth.uid;
    }
  }
}

Эти правила по сути гласят, что любой вошедший в систему пользователь приложения может создать для себя документ в любой коллекции. После создания только тот пользователь, который создал этот документ, сможет просматривать, обновлять или удалять этот документ.

Запустите приложение

Теперь вы готовы запустить приложение! Откройте папку make-it-so-android/start в Android Studio и запустите приложение (это можно сделать с помощью эмулятора Android или реального устройства Android).

3. Аутентификация Firebase

Какую функцию вы собираетесь добавить?

В текущем состоянии примера приложения Make It So пользователь может начать использовать приложение без предварительного входа в систему. Для этого используется анонимная аутентификация. Однако анонимные учетные записи не позволяют пользователю получать доступ к своим данным на других устройствах или даже в будущих сеансах. Хотя анонимная проверка подлинности полезна для теплого подключения, вы всегда должны предоставлять пользователям возможность перейти на другую форму входа. Имея это в виду, в этой лаборатории кода вы добавите аутентификацию по электронной почте и паролю в приложение Make It So.

Время кодировать!

Как только пользователь создает учетную запись, введя адрес электронной почты и пароль, вам необходимо запросить у Firebase Authentication API учетные данные электронной почты, а затем связать новые учетные данные с анонимной учетной записью. Откройте файл AccountServiceImpl.kt в Android Studio и обновите функцию linkAccount , чтобы она выглядела следующим образом:

модель/сервис/импл/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 :

экраны/sign_up/SignUpViewModel.kt

launchCatching {
    accountService.linkAccount(email, password)
    openAndPopUp(SETTINGS_SCREEN, SIGN_UP_SCREEN)
}

Сначала он пытается пройти аутентификацию, и если вызов успешен, он переходит к следующему экрану ( SettingsScreen ). Поскольку вы выполняете эти вызовы внутри блока launchCatching , если в первой строке произойдет ошибка, исключение будет перехвачено и обработано, а вторая строка вообще не будет достигнута.

Как только экран SettingsScreen откроется снова, вам необходимо убедиться, что параметры «Вход» и «Создать учетную запись» исчезли, поскольку теперь пользователь уже аутентифицирован. Для этого давайте заставим SettingsViewModel прослушивать статус текущего пользователя (доступен в AccountService.kt ), чтобы проверить, является ли учетная запись анонимной или нет. Для этого обновите uiState в SettingsViewModel.kt , чтобы он выглядел следующим образом:

экраны/настройки/SettingsViewModel.kt

val uiState = accountService.currentUser.map {
    SettingsUiState(it.isAnonymous)
}

Последнее, что вам нужно сделать, это обновить uiState в SettingsScreen.kt , чтобы собирать состояния, создаваемые SettingsViewModel :

экраны/настройки/SettingsScreen.kt

val uiState by viewModel.uiState.collectAsState(
    initial = SettingsUiState(false)
)

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

Время тестировать!

Запустите Make it So и перейдите к настройкам, щелкнув значок шестеренки в правом верхнем углу экрана. Оттуда выберите опцию создания учетной записи:

Экран настроек «Сделай это так»Экран регистрации «Сделай это так»

Введите действительный адрес электронной почты и надежный пароль, чтобы создать учетную запись. Это должно сработать, и вы будете перенаправлены на страницу настроек, где вы увидите две новые опции: выйти и удалить свою учетную запись. Вы можете проверить новую учетную запись, созданную на панели аутентификации на консоли Firebase, щелкнув вкладку «Пользователи».

4. Облачный Firestore

Какую функцию вы собираетесь добавить?

Для Cloud Firestore вы добавите прослушиватель в коллекцию Firestore, в которой хранятся документы, представляющие задачи, отображаемые в Make it So. Добавив этот прослушиватель, вы будете получать все обновления этой коллекции.

Время кодировать!

Обновите Flow , доступный в StorageServiceImpl.kt , чтобы он выглядел следующим образом:

модель/сервис/импл/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 отображался так же, как и в сервисе:

экраны/задачи/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 , вы увидите встроенную функцию, называемую трассировкой. Эта функция вызывает API мониторинга производительности для создания пользовательской трассировки, передавая имя трассировки в качестве параметра. Другой параметр, который вы видите, — это блок кода, который вы хотите отслеживать. Метрикой по умолчанию, собираемой для каждой трассировки, является время, необходимое для полного запуска:

модель/сервис/Performance.kt

inline fun <T> trace(name: String, block: Trace.() -> T): T = Trace.create(name).trace(block)

Вы можете выбрать, какие части кодовой базы, по вашему мнению, важно измерить, и добавить к ним собственные трассировки. Вот пример добавления пользовательской трассировки к функции linkAccount , которую вы видели ранее (в AccountServiceImpl.kt ) в этой лаборатории кода:

модель/сервис/импл/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 и обновите реализацию этих двух функций:

модель/сервис/импл/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 следующее:

экраны/задачи/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!

Дальнейшее чтение

Справочная документация