Utwórz aplikację na Androida za pomocą Firebase i Jetpack Compose

1. Wstęp

Ostatnia aktualizacja: 2022-11-16

Tworzenie aplikacji na Androida przy użyciu Firebase i Jetpack Compose

Podczas tych zajęć z programowania utworzysz aplikację na Androida o nazwie Make It So . Interfejs użytkownika tej aplikacji jest w całości zbudowany przy użyciu Jetpack Compose , który jest nowoczesnym zestawem narzędzi dla systemu Android do tworzenia natywnego interfejsu użytkownika — jest intuicyjny i wymaga mniej kodu niż pisanie plików .xml i wiązanie ich z działaniami, fragmentami lub widokami.

Pierwszym krokiem do zrozumienia, jak dobrze współpracują Firebase i Jetpack Compose, jest zrozumienie nowoczesnej architektury Androida. Dobra architektura sprawia, że ​​system jest łatwy do zrozumienia, łatwy w rozwoju i utrzymaniu, ponieważ bardzo wyraźnie pokazuje, w jaki sposób komponenty są zorganizowane i komunikują się ze sobą. W świecie Androida zalecana architektura nazywa się Model - View - ViewModel . Model reprezentuje warstwę, która uzyskuje dostęp do danych w aplikacji. Widok jest warstwą interfejsu użytkownika i nie powinien nic wiedzieć o logice biznesowej. ViewModel to miejsce, w którym stosowana jest logika biznesowa, co czasami wymaga, aby ViewModel wywołał warstwę modelu .

Zdecydowanie zalecamy przeczytanie tego artykułu , aby zrozumieć, w jaki sposób Model — Widok — ViewModel jest stosowany w aplikacji na Androida utworzonej za pomocą Jetpack Compose, ponieważ ułatwi to zrozumienie bazy kodu i łatwiejsze wykonanie kolejnych kroków.

Co zbudujesz

Make It So to prosta aplikacja do tworzenia list rzeczy do zrobienia, która umożliwia użytkownikowi dodawanie i edytowanie zadań, dodawanie flag, priorytetów i terminów oraz oznaczanie zadań jako ukończonych. Poniższe obrazy przedstawiają dwie główne strony tej aplikacji: stronę tworzenia zadań i stronę główną z listą utworzonych zadań.

Zrób to tak, aby dodać ekran zadaniaStwórz taki ekran główny

Dodasz kilka funkcji, których brakuje w tej aplikacji:

  • Uwierzytelnij użytkowników za pomocą adresu e-mail i hasła
  • Dodaj słuchacza do kolekcji Firestore i spraw, aby interfejs użytkownika reagował na zmiany
  • Dodaj niestandardowe ślady, aby monitorować wydajność określonego kodu w aplikacji
  • Utwórz przełącznik funkcji za pomocą Zdalnej konfiguracji i użyj wdrożenia etapowego, aby go uruchomić

Czego się dowiesz

  • Jak korzystać z uwierzytelniania Firebase, monitorowania wydajności, zdalnej konfiguracji i Cloud Firestore w nowoczesnej aplikacji na Androida
  • Jak dopasować interfejsy API Firebase do architektury MVVM
  • Jak odzwierciedlić zmiany wprowadzone za pomocą interfejsów API Firebase w interfejsie użytkownika Compose

Co będziesz potrzebował

2. Pobierz przykładową aplikację i skonfiguruj Firebase

Pobierz kod przykładowej aplikacji

Sklonuj repozytorium GitHub z wiersza poleceń:

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

Skonfiguruj Firebase

Pierwszą rzeczą, którą musisz zrobić, to przejść do konsoli Firebase i utworzyć projekt Firebase, klikając przycisk „+ Dodaj projekt”, jak widać poniżej:

Konsola Firebase

Postępuj zgodnie z instrukcjami wyświetlanymi na ekranie, aby zakończyć tworzenie projektu.

Wewnątrz każdego projektu Firebase możesz tworzyć różne aplikacje: na Androida, iOS, Web, Flutter i Unity. Wybierz opcję Androida, jak widać tutaj:

Omówienie projektu Firebase

Następnie wykonaj następujące kroki:

  1. Wpisz com.example.makeitso jako nazwę pakietu i opcjonalnie wprowadź pseudonim. W przypadku tych zajęć z programowania nie trzeba dodawać certyfikatu podpisywania debugowania.
  2. Kliknij Dalej , aby zarejestrować aplikację i uzyskać dostęp do pliku konfiguracyjnego Firebase.
  3. Kliknij Pobierz plik google-services.json, aby pobrać plik konfiguracyjny i zapisać go w katalogu make-it-so-android/app .
  4. Kliknij Następny . Ponieważ zestawy SDK Firebase są już zawarte w pliku build.gradle w przykładowym projekcie, kliknij Dalej , aby przejść do Następnych kroków .
  5. Kliknij Kontynuuj do konsoli, aby zakończyć.

Aby aplikacja Make it So działała poprawnie, przed przejściem do kodu musisz wykonać dwie rzeczy w konsoli: włączyć dostawców uwierzytelniania i utworzyć bazę danych Firestore. Najpierw włączmy uwierzytelnianie, aby użytkownicy mogli zalogować się do aplikacji:

  1. Z menu Kompilacja wybierz opcję Uwierzytelnianie , a następnie kliknij opcję Rozpocznij .
  2. Na karcie Metoda logowania wybierz opcję E-mail/hasło i włącz ją.
  3. Następnie kliknij Dodaj nowego dostawcę i wybierz i włącz opcję Anonimowy .

Następnie skonfiguruj Firestore. Będziesz używać Firestore do przechowywania zadań zalogowanego użytkownika. Każdy użytkownik otrzyma własny dokument w ramach zbioru bazy danych.

  1. Z menu Kompilacja wybierz Firestore , a następnie kliknij Utwórz bazę danych .
  2. Pozostaw opcję Start w trybie produkcyjnym włączoną i kliknij Dalej .
  3. Po wyświetleniu monitu wybierz lokalizację, w której będą przechowywane dane Cloud Firestore. Tworząc aplikację produkcyjną, chcesz, aby znajdowała się ona w regionie zbliżonym do większości Twoich użytkowników i wspólnym z innymi usługami Firebase, takimi jak Funkcje. W przypadku tych zajęć z programowania możesz zachować region domyślny lub wybrać region najbliższy Tobie.
  4. Kliknij Włącz, aby udostępnić bazę danych Firestore.

Poświęćmy chwilę na zbudowanie solidnych reguł bezpieczeństwa w bazie danych Firestore. Otwórz panel Firestore i przejdź do karty Reguły . Następnie zaktualizuj Reguły bezpieczeństwa, aby wyglądały tak:

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;
    }
  }
}

Zasady te zasadniczo mówią, że każdy zalogowany użytkownik aplikacji może utworzyć dla siebie dokument w dowolnej kolekcji. Następnie po utworzeniu tylko użytkownik, który utworzył ten dokument, będzie mógł go przeglądać, aktualizować i usuwać.

Uruchom aplikację

Teraz jesteś gotowy do uruchomienia aplikacji! Otwórz folder make-it-so-android/start w Android Studio i uruchom aplikację (można to zrobić za pomocą emulatora Androida lub prawdziwego urządzenia z Androidem).

3. Uwierzytelnianie Firebase

Którą funkcję zamierzasz dodać?

W bieżącym stanie przykładowej aplikacji Make It So użytkownik może rozpocząć korzystanie z aplikacji bez konieczności wcześniejszego logowania się. Aby to osiągnąć, wykorzystuje anonimowe uwierzytelnianie. Jednak konta anonimowe nie pozwalają użytkownikowi na dostęp do swoich danych na innych urządzeniach ani nawet w przyszłych sesjach. Chociaż uwierzytelnianie anonimowe jest przydatne w przypadku ciepłego wdrożenia, należy zawsze zapewnić użytkownikom opcję przejścia na inną formę logowania. Mając to na uwadze, podczas tych zajęć z programowania dodasz uwierzytelnianie za pomocą poczty elektronicznej i hasła do aplikacji Make It So.

Czas na kodowanie!

Gdy tylko użytkownik utworzy konto, wpisując adres e-mail i hasło, musisz poprosić interfejs Firebase Authentication API o dane uwierzytelniające e-mail, a następnie połączyć nowe dane uwierzytelniające z anonimowym kontem. Otwórz plik AccountServiceImpl.kt w Android Studio i zaktualizuj funkcję linkAccount , aby wyglądała następująco:

model/usługa/impl/AccountServiceImpl.kt

override suspend fun linkAccount(email: String, password: String) {
    val credential = EmailAuthProvider.getCredential(email, password)
    auth.currentUser!!.linkWithCredential(credential).await()
}

Teraz otwórz plik SignUpViewModel.kt i wywołaj funkcję service linkAccount w bloku launchCatching funkcji onSignUpClick :

screens/sign_up/SignUpViewModel.kt

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

Najpierw próbuje się uwierzytelnić, a jeśli połączenie się powiedzie, przechodzi do następnego ekranu ( SettingsScreen ). Jeśli podczas wykonywania tych wywołań w bloku launchCatching wystąpi błąd w pierwszej linii, wyjątek zostanie przechwycony i obsłużony, a druga linia w ogóle nie zostanie osiągnięta.

Gdy tylko SettingsScreen zostanie ponownie otwarty, musisz upewnić się, że opcje Zaloguj się i Utwórz konto zniknęły, ponieważ teraz użytkownik jest już uwierzytelniony. Aby to zrobić, sprawmy, aby SettingsViewModel nasłuchiwał statusu bieżącego użytkownika (dostępnego w AccountService.kt ), aby sprawdzić, czy konto jest anonimowe, czy nie. Aby to zrobić, zaktualizuj uiState w SettingsViewModel.kt , aby wyglądał następująco:

screens/ustawienia/SettingsViewModel.kt

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

Ostatnią rzeczą, którą musisz zrobić, to zaktualizować uiState w SettingsScreen.kt , aby zbierać stany emitowane przez SettingsViewModel :

ekrany/ustawienia/SettingsScreen.kt

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

Teraz za każdym razem, gdy zmieni się użytkownik, SettingsScreen będzie się ponownie komponował, aby wyświetlić opcje zgodnie z nowym stanem uwierzytelnienia użytkownika.

Czas przetestować!

Uruchom Make it So i przejdź do ustawień, klikając ikonę koła zębatego w prawym górnym rogu ekranu. Następnie kliknij opcję utwórz konto:

Ekran ustawień Zrób to takZrób to, więc ekran rejestracji

Wpisz prawidłowy adres e-mail i silne hasło, aby utworzyć konto. Powinno zadziałać i powinieneś zostać przekierowany na stronę ustawień, gdzie zobaczysz dwie nowe opcje: wylogowanie się i usunięcie konta. Możesz sprawdzić nowe konto utworzone w panelu uwierzytelniania w konsoli Firebase, klikając kartę Użytkownicy.

4. Chmura Firestore

Którą funkcję zamierzasz dodać?

W przypadku Cloud Firestore dodasz odbiornik do kolekcji Firestore, która przechowuje dokumenty reprezentujące zadania wyświetlane w Make it So . Po dodaniu tego słuchacza będziesz otrzymywać wszystkie aktualizacje wprowadzone w tej kolekcji.

Czas na kodowanie!

Zaktualizuj Flow dostępny w StorageServiceImpl.kt , aby wyglądał następująco:

model/usługa/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()
      }

Ten kod dodaje słuchacza do kolekcji zadań na podstawie user.id . Każde zadanie jest reprezentowane przez dokument w kolekcji o nazwie tasks i każde z nich ma pole o nazwie userId . Należy pamiętać, że nowy Flow zostanie wyemitowany, jeśli status currentUser ulegnie zmianie (na przykład poprzez wylogowanie).

Teraz musisz sprawić, aby Flow w TasksViewModel.kt odzwierciedlał taki sam jak w usłudze:

screens/zadania/TasksViewModel.kt

val tasks = storageService.tasks

Ostatnią rzeczą będzie to, aby composable function w TasksScreens.kt , która reprezentuje interfejs użytkownika, była świadoma tego przepływu i zbierała go jako stan. Za każdym razem, gdy stan się zmieni, funkcja umożliwiająca komponowanie automatycznie ułoży się ponownie i wyświetli użytkownikowi najnowszy stan. Dodaj to do TasksScreen composable function :

ekrany/zadania/TasksScreen.kt

val tasks = viewModel
    .tasks
    .collectAsStateWithLifecycle(emptyList())

Gdy funkcja komponowalna uzyska dostęp do tych stanów, możesz zaktualizować LazyColumn (która jest strukturą używaną do wyświetlania listy na ekranie), aby wyglądała następująco:

ekrany/zadania/TasksScreen.kt

LazyColumn {
    items(tasks.value, key = { it.id }) { taskItem ->
        TaskItem( [...] )
    }
}

Czas przetestować!

Aby sprawdzić, czy zadziałało, dodaj nowe zadanie za pomocą aplikacji (klikając przycisk dodawania w prawym dolnym rogu ekranu). Po zakończeniu tworzenia zadania powinno ono pojawić się w kolekcji Firestore w konsoli Firestore. Jeśli zalogujesz się do Make it So na innych urządzeniach z tym samym kontem, będziesz mógł edytować swoje rzeczy do zrobienia i oglądać ich aktualizację na wszystkich urządzeniach w czasie rzeczywistym.

5. Monitorowanie wydajności

Którą funkcję zamierzasz dodać?

Wydajność jest bardzo ważną rzeczą, na którą należy zwrócić uwagę, ponieważ użytkownicy prawdopodobnie zrezygnują z korzystania z Twojej aplikacji, jeśli wydajność nie będzie dobra, a wykonanie przy jej użyciu prostego zadania zajmie im zbyt dużo czasu. Dlatego czasami warto zebrać pewne dane dotyczące konkretnej podróży, jaką użytkownik odbywa w Twojej aplikacji. Aby Ci w tym pomóc, Firebase Performance Monitoring oferuje niestandardowe ślady . Wykonaj kolejne kroki, aby dodać niestandardowe ślady i zmierzyć wydajność w różnych fragmentach kodu w Make it So.

Czas na kodowanie!

Jeśli otworzysz plik Performance.kt , zobaczysz wbudowaną funkcję o nazwie Trace. Ta funkcja wywołuje interfejs API monitorowania wydajności w celu utworzenia niestandardowego śledzenia, przekazując nazwę śledzenia jako parametr. Innym parametrem, który widzisz, jest blok kodu, który chcesz monitorować. Domyślną metryką zbieraną dla każdego śledzenia jest czas potrzebny do całkowitego uruchomienia:

model/usługa/Performance.kt

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

Możesz wybrać, które części bazy kodu uważasz za ważne do zmierzenia i dodać do nich niestandardowe ślady. Oto przykład dodania niestandardowego śledzenia do funkcji linkAccount , który widziałeś wcześniej (w AccountServiceImpl.kt ) w tym ćwiczeniu z programowania:

model/usługa/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()
  }

Teraz twoja kolej! Dodaj niestandardowe ślady do aplikacji Make it So i przejdź do następnej sekcji, aby sprawdzić, czy działa zgodnie z oczekiwaniami.

Czas przetestować!

Po zakończeniu dodawania niestandardowych śladów uruchom aplikację i pamiętaj, aby kilka razy skorzystać z funkcji, które chcesz zmierzyć. Następnie przejdź do konsoli Firebase i przejdź do panelu Wydajność . Na dole ekranu znajdziesz trzy zakładki: Żądania sieciowe , Ślady niestandardowe i Renderowanie ekranu .

Przejdź do zakładki Niestandardowe ślady i sprawdź, czy wyświetlają się tam ślady dodane w bazie kodu oraz czy widzisz, ile czasu zwykle zajmuje wykonanie tych fragmentów kodu.

6. Zdalna konfiguracja

Którą funkcję zamierzasz dodać?

Istnieje wiele przypadków użycia Zdalnej konfiguracji, od zdalnej zmiany wyglądu aplikacji po konfigurowanie różnych zachowań dla różnych segmentów użytkowników. Podczas tych zajęć z programowania użyjesz funkcji Remote Config do utworzenia przełącznika funkcji, który pokaże lub ukryje nową funkcję zadania edycji w aplikacji Make it So.

Czas na kodowanie!

Pierwszą rzeczą, którą musisz zrobić, to utworzyć konfigurację w konsoli Firebase. W tym celu należy przejść do panelu Remote Config i kliknąć przycisk Dodaj parametr . Wypełnij pola zgodnie z obrazkiem poniżej:

Zdalna konfiguracja Okno dialogowe Utwórz parametr

Po wypełnieniu wszystkich pól możesz kliknąć przycisk Zapisz , a następnie Opublikować . Teraz, gdy parametr jest już utworzony i dostępny w bazie kodu, musisz dodać kod, który pobierze nowe wartości do Twojej aplikacji. Otwórz plik ConfigurationServiceImpl.kt i zaktualizuj implementację tych dwóch funkcji:

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()

Pierwsza funkcja pobiera wartości z serwera i jest wywoływana zaraz po uruchomieniu aplikacji w SplashViewModel.kt . To najlepszy sposób, aby mieć pewność, że najbardziej aktualne wartości będą dostępne na wszystkich ekranach od samego początku. Zmiana interfejsu użytkownika lub zachowania aplikacji później, gdy użytkownik jest w trakcie wykonywania jakiejś czynności, nie jest dobrym doświadczeniem!

Druga funkcja zwraca wartość logiczną opublikowaną dla parametru, który właśnie utworzyłeś w konsoli. Będziesz musiał pobrać te informacje w TasksViewModel.kt , dodając następujące elementy do funkcji loadTaskOptions :

screens/zadania/TasksViewModel.kt

fun loadTaskOptions() {
  val hasEditOption = configurationService.isShowTaskEditButtonConfig
  options.value = TaskActionOption.getOptions(hasEditOption)
}

Pobierasz wartość z pierwszego wiersza i używasz jej do załadowania opcji menu dla elementów zadania w drugim wierszu. Jeśli wartość to false , oznacza to, że menu nie będzie zawierało opcji edycji. Teraz, gdy masz już listę opcji, musisz sprawić, aby interfejs użytkownika wyświetlał ją poprawnie. Tworząc aplikację za pomocą Jetpack Compose, musisz poszukać composable function , która deklaruje, jak powinien wyglądać interfejs użytkownika na TasksScreen . Otwórz więc plik TasksScreen.kt i zaktualizuj LazyColum , aby wskazywał opcje dostępne w TasksViewModel.kt :

ekrany/zadania/TasksScreen.kt

val options by viewModel.options

LazyColumn {
  items(tasks.value, key = { it.id }) { taskItem ->
    TaskItem(
      options = options,
      [...]
    )
  }
}

TaskItem to kolejna composable function , która deklaruje, jak powinien wyglądać interfejs użytkownika pojedynczego zadania. Każde zadanie ma menu z opcjami, które wyświetla się, gdy użytkownik kliknie ikonę z trzema kropkami na jego końcu.

Czas przetestować!

Teraz możesz uruchomić aplikację! Sprawdź, czy wartość opublikowana za pomocą konsoli Firebase odpowiada zachowaniu aplikacji:

  • Jeśli to false , po kliknięciu ikony z trzema kropkami powinieneś zobaczyć tylko dwie opcje;
  • Jeśli to true , po kliknięciu ikony z trzema kropkami powinieneś zobaczyć trzy opcje;

Spróbuj kilka razy zmienić wartość w konsoli i ponownie uruchomić aplikację. Tak łatwo jest uruchamiać nowe funkcje w aplikacji za pomocą Zdalnej konfiguracji!

7. Gratulacje

Gratulacje, udało Ci się stworzyć aplikację na Androida przy użyciu Firebase i Jetpack Compose!

Dodałeś uwierzytelnianie Firebase, monitorowanie wydajności, zdalną konfigurację i Cloud Firestore do aplikacji na Androida w całości zbudowanej za pomocą Jetpack Compose dla interfejsu użytkownika i dopasowałeś ją do zalecanej architektury MVVM!

Dalsza lektura

Dokumenty referencyjne