בנה אפליקציית אנדרואיד עם Firebase ו-Jetpack Compose

1. הקדמה

עדכון אחרון: 16-11-2022

בניית אפליקציית אנדרואיד עם Firebase ו-Jetpack Compose

ב-codelab זה, תבנה אפליקציית אנדרואיד בשם Make It So. ממשק המשתמש של אפליקציה זו בנוי כולו עם Jetpack Compose , שהוא ערכת הכלים המודרנית של אנדרואיד לבניית ממשק משתמש מקורי - הוא אינטואיטיבי ודורש פחות קוד מאשר כתיבת קבצי .xml וקשירתם לפעילויות, פרגמנטים או תצוגות.

הצעד הראשון כדי להבין עד כמה Firebase ו-Jetpack Compose עובדים יחד הוא הבנת ארכיטקטורת אנדרואיד מודרנית. ארכיטקטורה טובה הופכת את המערכת לקלה להבנה, קלה לפיתוח וקלה לתחזוקה, שכן היא מבהירה היטב כיצד הרכיבים מאורגנים ומתקשרים זה עם זה. בעולם האנדרואיד הארכיטקטורה המומלצת נקראת Model - View - ViewModel . המודל מייצג את השכבה שניגשת לנתונים באפליקציה. התצוגה היא שכבת ממשק המשתמש ולא אמורה לדעת דבר על ההיגיון העסקי. ו- ViewModel הוא המקום שבו מיושם ההיגיון העסקי, שלעתים מחייב את ViewModel לקרוא לשכבת המודל .

אנו ממליצים בחום לקרוא מאמר זה כדי להבין כיצד מודל - תצוגה - ViewModel מיושם על אפליקציית אנדרואיד שנבנתה עם 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. בחר באפשרות אנדרואיד, כפי שאתה רואה כאן:

סקירת פרויקט Firebase

לאחר מכן בצע את השלבים הבאים:

  1. הזן com.example.makeitso כשם החבילה, ולחלופין, הזן כינוי. עבור מעבדת קוד זה, אינך צריך להוסיף את אישור החתימה באגים.
  2. לחץ על הבא כדי לרשום את האפליקציה שלך ולגשת לקובץ התצורה של Firebase.
  3. לחץ על הורד את google-services.json כדי להוריד את קובץ התצורה שלך ולשמור אותו בספריית make-it-so-android/app .
  4. הקש "הבא . מכיוון ש-SDKs של 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 באנדרואיד סטודיו והפעילו את האפליקציה (ניתן לעשות זאת באמצעות אמולטור אנדרואיד או מכשיר אנדרואיד אמיתי).

3. אימות Firebase

איזה תכונה אתה הולך להוסיף?

במצב הנוכחי של אפליקציית Make It So לדוגמה, משתמש יכול להתחיל להשתמש באפליקציה ללא צורך בכניסה תחילה. הוא משתמש באימות אנונימי כדי להשיג זאת. עם זאת, חשבונות אנונימיים אינם מאפשרים למשתמש לגשת לנתונים שלו במכשירים אחרים או אפילו בהפעלות עתידיות. למרות שאימות אנונימי שימושי לכניסה חמה, עליך תמיד לספק למשתמשים אפשרות להמיר לצורת כניסה אחרת. עם זאת בחשבון, במעבדת הקוד הזה, תוסיף אימות דוא"ל וסיסמה לאפליקציית Make It So.

הגיע הזמן לקוד!

ברגע שהמשתמש יוצר חשבון, על ידי הקלדת אימייל וסיסמה, עליך לבקש מ-Firebase Authentication API אישור אימייל, ולאחר מכן לקשר את האישור החדש לחשבון האנונימי. פתח את הקובץ 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 וקרא לפונקציית service 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 כך שייראה כך:

מסכים/הגדרות/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. 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 , המייצגת את ה-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 Console. אם תיכנס ל- 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. כדי לעשות זאת, עליך לנווט אל לוח המחוונים של 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 . זו הדרך הטובה ביותר להבטיח שהערכים המעודכנים ביותר יהיו זמינים בכל המסכים כבר מההתחלה. זו לא חווית משתמש טובה אם תשנה את ממשק המשתמש או את התנהגות האפליקציה מאוחר יותר, כשהמשתמש נמצא באמצע לעשות משהו!

הפונקציה השנייה היא החזרת הערך הבוליאני שפורסם עבור הפרמטר שיצרת זה עתה ב-Console. ואתה תצטרך לאחזר מידע זה ב- 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 , אתה אמור לראות שלוש אפשרויות בעת לחיצה על סמל שלוש הנקודות;

נסה לשנות את הערך מספר פעמים ב-Console ולהפעיל מחדש את האפליקציה. עד כדי כך קל להשיק תכונות חדשות באפליקציה שלך באמצעות Remote Config!

7. מזל טוב

מזל טוב, בנית בהצלחה אפליקציית אנדרואיד עם Firebase ו-Jetpack Compose!

הוספת את אימות Firebase, ניטור ביצועים, תצורה מרחוק ו-Cloud Firestore לאפליקציית אנדרואיד שנבנתה כולה עם Jetpack Compose עבור ממשק המשתמש, וגרמת לה להשתלב בארכיטקטורת MVVM המומלצת!

לקריאה נוספת

מסמכי עזר