1. 簡介
上次更新時間:2022 年 11 月 16 日
使用 Firebase 和 Jetpack Compose 建構 Android 應用程式
在本程式碼研究室中,您將建構名為 Make It So 的 Android 應用程式。此應用程式的 UI 完全採用 Jetpack Compose 建構,這是 Android 用於建構原生 UI 的新型工具包,使用起來直覺且所需程式碼比撰寫 .xml 檔案並將其繫結至活動、Fragment 或 View 少。
如要瞭解 Firebase 和 Jetpack Compose 的搭配運作情形,第一步是瞭解現代 Android 架構。良好的架構可讓系統易於理解、開發及維護,因為它會清楚說明元件的組織方式和彼此間的溝通方式。在 Android 世界中,建議的架構稱為 Model - View - ViewModel。Model 代表應用程式中存取資料的層。View 是 UI 層,不應知道任何商業邏輯。而 ViewModel 是套用商業邏輯的地方,有時需要 ViewModel 呼叫 Model 層。
強烈建議您參閱本文,瞭解如何將 Model - View - ViewModel 套用至使用 Jetpack Compose 建構的 Android 應用程式,因為這有助於您更容易瞭解程式碼集,並更輕鬆地完成後續步驟。
建構項目
Make It So 是一款簡單的待辦事項清單應用程式,可讓使用者新增及編輯工作、新增標記、優先順序和截止日期,以及將工作標示為已完成。下方圖片顯示此應用程式的兩個主要頁面:工作建立頁面和顯示已建立工作清單的主頁面。
您將新增此應用程式缺少的部分功能:
- 使用電子郵件地址和密碼驗證使用者
- 在 Firestore 集合中新增監聽器,讓 UI 對變更做出反應
- 新增自訂追蹤記錄,監控應用程式中特定程式碼的效能
- 使用遠端設定建立功能切換鈕,並透過階段性推出作業發布
課程內容
- 如何在現代 Android 應用程式中使用 Firebase 驗證、Performance Monitoring、遠端設定和 Cloud Firestore
- 如何讓 Firebase API 符合 MVVM 架構
- 如何在 Compose UI 中反映使用 Firebase API 所做的變更
事前準備
- Android Studio Flamingo+
- 搭載 API 21 以上版本的 Android Emulator
- 熟悉 Kotlin 程式設計語言
2. 取得範例應用程式並設定 Firebase
取得範例應用程式的程式碼
從指令列複製 GitHub 存放區:
git clone https://github.com/FirebaseExtended/make-it-so-android.git
建立 Firebase 專案
首先,請前往 Firebase 主控台,然後按一下「+ 新增專案」按鈕建立 Firebase 專案,如下所示:
按照畫面上的步驟完成專案建立程序。
將 Android 應用程式新增至 Firebase 專案
您可以在 Firebase 專案中註冊不同的應用程式,包括 Android、iOS、網頁、Flutter 和 Unity。
請選擇 Android 選項,如下所示:
然後按照下列步驟操作:
- 輸入
com.example.makeitso
做為套件名稱,並視需要輸入暱稱。在本程式碼研究室中,您不需要新增偵錯簽署憑證。 - 點選「下一步」即可註冊應用程式,並存取 Firebase 設定檔。
- 按一下「Download google-services.json」,下載設定檔並儲存在
make-it-so-android/app
目錄中。 - 點選「下一步」。由於範例專案的
build.gradle
檔案中已包含 Firebase SDK,請點選「Next」跳至「Next steps」。 - 按一下「Continue to console」即可完成。
如要讓 Make it So 應用程式正常運作,請在跳轉至程式碼前,先在控制台中執行兩項操作:啟用驗證服務供應器,並建立 Firestore 資料庫。
設定驗證
首先,我們要啟用驗證功能,讓使用者能夠登入應用程式:
- 在「Build」選單中,依序選取「Authentication」和「Get Started」。
- 在「登入方式」資訊卡中,選取「電子郵件/密碼」並啟用。
- 接著,按一下「新增供應者」,然後選取並啟用「匿名」。
設定 Cloud Firestore
接著,請設定 Firestore。您將使用 Firestore 儲存已登入使用者的任務。每位使用者都會在資料庫的集合中取得自己的文件。
- 在 Firebase 主控台的左側面板中展開「Build」,然後選取「Firestore database」。
- 按一下 [Create database] (建立資料庫)。
- 將「資料庫 ID」設為
(default)
。 - 選取資料庫的位置,然後按一下「Next」。
如果是實際應用程式,請選擇距離使用者較近的位置。 - 按一下「以測試模式啟動」。詳閱安全性規則免責事項。
在本節的後續步驟中,您將新增安全性規則來保護資料。請勿發布或公開應用程式,除非您已為資料庫新增安全性規則。 - 按一下「建立」。
讓我們花點時間為 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;
}
}
}
這些規則基本上表示,任何已登入應用程式的使用者都能在任何集合內建立文件。建立後,只有建立該文件的使用者才能查看、更新或刪除該文件。
執行應用程式
您現在可以執行應用程式了!在 Android Studio 中開啟 make-it-so-android/start
資料夾,然後執行應用程式 (可使用 Android Emulator 或實際的 Android 裝置執行)。
3. Firebase 驗證
您要新增哪項功能?
在 Make It So 範例應用程式的目前狀態下,使用者可以開始使用應用程式,無須先登入。這項功能會使用匿名驗證來達成此目標。不過,匿名帳戶無法讓使用者存取其他裝置上的資料,甚至無法在日後的工作階段存取。雖然匿名驗證功能可用於溫暖式新手上路流程,但您應一律提供使用者轉換為其他登入表單的選項。考量到這一點,您將在本程式碼研究室中,為 Make It So 應用程式新增電子郵件和密碼驗證機制。
該寫程式碼了!
使用者只要輸入電子郵件地址和密碼建立帳戶,您就必須向 Firebase Authentication API 索取電子郵件憑證,然後將新憑證連結至匿名帳戶。在 Android Studio 中開啟 AccountServiceImpl.kt
檔案,並更新 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
,並在 onSignUpClick
函式的 launchCatching
區塊中呼叫服務 linkAccount
函式:
screens/sign_up/SignUpViewModel.kt
launchCatching {
accountService.linkAccount(email, password)
openAndPopUp(SETTINGS_SCREEN, SIGN_UP_SCREEN)
}
系統會先嘗試驗證,如果呼叫成功,就會繼續前往下一個畫面 (SettingsScreen
)。當您在 launchCatching
區塊中執行這些呼叫時,如果第一行發生錯誤,系統會擷取並處理例外狀況,而不會執行第二行。
SettingsScreen
重新開啟後,您必須確認「Sign in」和「Create account」選項已消失,因為使用者已完成驗證。為此,讓 SettingsViewModel
監聽目前使用者的狀態 (可在 AccountService.kt
中使用),以便檢查帳戶是否為匿名帳戶。方法是更新 SettingsViewModel.kt
中的 uiState
,使其如下所示:
screens/settings/SettingsViewModel.kt
val uiState = accountService.currentUser.map {
SettingsUiState(it.isAnonymous)
}
最後,您需要更新 SettingsScreen.kt
中的 uiState
,收集 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 中顯示的任務的文件。新增此事件監聽器後,您就會收到對此集合所做的每項更新。
該寫程式碼了!
更新 StorageServiceImpl.kt
中可用的 Flow
,如下所示:
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
。
接下來,您需要讓 TasksViewModel.kt
中的 Flow
與服務中的 Flow
一致:
screens/tasks/TasksViewModel.kt
val tasks = storageService.tasks
最後,請讓 TasksScreens.kt
中的 composable function
(代表 UI) 注意這個流程,並將其收集為狀態。每次狀態變更時,可組合函式都會自動重新組合,並向使用者顯示最新狀態。將以下內容新增至 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 效能監控提供自訂追蹤記錄。請按照下列步驟新增自訂追蹤,並在「Make it So」中評估不同程式碼的效能。
該寫程式碼了!
如果您開啟 Performance.kt
檔案,就會看到名為 trace 的內嵌函式。這個函式會呼叫 Performance Monitoring 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 控制台並前往效能資訊主頁。畫面底部會顯示三個分頁:「網路要求」、「自訂追蹤記錄」和「螢幕算繪」。
前往「Custom traces」分頁,確認程式碼庫中新增的追蹤記錄是否顯示在該分頁中,並查看執行這些程式碼通常需要多長時間。
6. 遠端設定
您要新增哪項功能?
遠端設定的用途多元,從遠端變更應用程式外觀,到為不同使用者區隔設定不同行為皆可。在本程式碼研究室中,您將使用 Remote Config 建立功能切換鈕,在 Make it So 應用程式中顯示或隱藏新的「編輯工作」功能。
該寫程式碼了!
首先,請在 Firebase 主控台中建立設定。如要這樣做,請前往 遠端設定資訊主頁,然後點選「新增參數」按鈕。按照下圖填寫欄位:
填妥所有欄位後,請按一下「儲存」按鈕,然後點選「發布」。參數已建立並可供程式碼集使用,因此您需要新增程式碼,以便在應用程式中擷取新值。請開啟 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
中)。這是確保所有畫面一開始就能顯示最新值的最佳方法。如果您在使用者執行某項操作時,稍後變更應用程式的 UI 或行為,這會導致使用者體驗不佳!
第二個函式會傳回針對您剛在控制台中建立的參數發布的布林值。您需要在 loadTaskOptions
函式中加入下列內容,才能在 TasksViewModel.kt
中擷取這項資訊:
screens/tasks/TasksViewModel.kt
fun loadTaskOptions() {
val hasEditOption = configurationService.isShowTaskEditButtonConfig
options.value = TaskActionOption.getOptions(hasEditOption)
}
您會擷取第一行中的值,並使用該值載入第二行中工作項目的選單選項。如果值為 false
,表示選單中不會包含編輯選項。您現在已取得選項清單,因此需要讓 UI 正確顯示選項。使用 Jetpack Compose 建構應用程式時,您需要尋找 composable function
,宣告 TasksScreen
的 UI 應有的外觀。因此,請開啟 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
,用於宣告單一工作項的 UI 應有的外觀。每個工作都有選單,當使用者按一下工作結尾處的三點圖示,就會顯示選項。
測試時間!
您現在可以執行應用程式了!確認您透過 Firebase 控制台發布的值與應用程式行為相符:
- 如果是
false
,點選三點圖示時,您應該只會看到兩個選項。 - 如果是
true
,點選三點圖示後,您應該會看到三個選項:
請嘗試在控制台中變更幾次值,然後重新啟動應用程式。透過遠端設定,您就能輕鬆在應用程式中推出新功能!
7. 恭喜!
恭喜,您已成功使用 Firebase 和 Jetpack Compose 建構 Android 應用程式!
您已將 Firebase 驗證、Performance Monitoring、遠端設定和 Cloud Firestore 新增至完全使用 Jetpack Compose 建構的 Android 應用程式 UI,並將其納入建議的 MVVM 架構!
延伸閱讀
- 使用 Firebase 和 Compose 建構 Android 應用程式
- 在 Jetpack Compose 應用程式中加入 Firebase 驗證
- 將 Cloud Firestore 新增至 Jetpack Compose 應用程式
- 在使用 Firebase 和 Compose 建構的 Android 應用程式中加入 Coroutines 和 Flow
- 在 Jetpack Compose 應用程式中新增 Firebase Performance Monitoring
- 將 Firebase 遠端設定新增至 Jetpack Compose 應用程式