Xây dựng ứng dụng Android bằng Firebase và Jetpack Compose

1. Giới thiệu

Cập nhật lần cuối: 2022-11-16

Xây dựng ứng dụng Android bằng Firebase và Jetpack Compose

Trong lớp học lập trình này, bạn sẽ xây dựng một ứng dụng Android có tên Make It So . Giao diện người dùng của ứng dụng này được xây dựng hoàn toàn bằng Jetpack Compose , đây là bộ công cụ hiện đại của Android để xây dựng giao diện người dùng gốc - nó trực quan và yêu cầu ít mã hơn so với việc ghi tệp .xml và liên kết chúng với Hoạt động, Phân đoạn hoặc Chế độ xem.

Bước đầu tiên để hiểu Firebase và Jetpack Compose phối hợp tốt như thế nào là hiểu kiến ​​trúc Android hiện đại. Một kiến ​​trúc tốt làm cho hệ thống dễ hiểu, dễ phát triển và dễ bảo trì, vì nó làm cho nó rất rõ ràng về cách các thành phần được tổ chức và giao tiếp với nhau. Trong thế giới Android, kiến ​​trúc được đề xuất có tên Model - View - ViewModel . Mô hình đại diện cho lớp truy cập Dữ liệu trong ứng dụng. Chế độ xem là lớp giao diện người dùng và không biết gì về logic nghiệp vụ. Và ViewModel là nơi áp dụng logic nghiệp vụ, đôi khi yêu cầu ViewModel gọi lớp Model .

Chúng tôi thực sự khuyên bạn nên đọc bài viết này để hiểu cách áp dụng Model - View - ViewModel cho ứng dụng Android được xây dựng bằng Jetpack Compose, vì nó sẽ giúp cơ sở mã dễ hiểu hơn và các bước tiếp theo dễ hoàn thành hơn.

Những gì bạn sẽ xây dựng

Make It So là một ứng dụng danh sách việc cần làm đơn giản cho phép người dùng thêm và chỉnh sửa các nhiệm vụ, thêm cờ, mức độ ưu tiên và ngày đến hạn cũng như đánh dấu các nhiệm vụ là đã hoàn thành. Những hình ảnh bên dưới hiển thị hai trang chính của ứng dụng này: trang tạo tác vụ và trang chính với danh sách các tác vụ được tạo.

Làm cho nó thành như vậy Màn hình Thêm tác vụMàn hình chính biến nó thành như vậy

Bạn sẽ thêm một số tính năng còn thiếu trong ứng dụng này:

  • Xác thực người dùng bằng email và mật khẩu
  • Thêm trình nghe vào bộ sưu tập Firestore và làm cho giao diện người dùng phản ứng với các thay đổi
  • Thêm dấu vết tùy chỉnh để theo dõi hiệu suất của mã cụ thể trong ứng dụng
  • Tạo chuyển đổi tính năng bằng Cấu hình từ xa và sử dụng triển khai theo giai đoạn để khởi chạy tính năng đó

Bạn sẽ học được gì

  • Cách sử dụng Xác thực Firebase, Giám sát hiệu suất, Cấu hình từ xa và Cloud Firestore trong ứng dụng Android hiện đại
  • Cách làm cho API Firebase phù hợp với kiến ​​trúc MVVM
  • Cách phản ánh những thay đổi được thực hiện với API Firebase trong giao diện người dùng Compose

Những gì bạn cần

2. Tải ứng dụng mẫu và thiết lập Firebase

Lấy mã của ứng dụng mẫu

Sao chép kho GitHub từ dòng lệnh:

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

Thiết lập căn cứ hỏa lực

Điều đầu tiên bạn cần làm là vào bảng điều khiển Firebase và tạo dự án Firebase bằng cách nhấp vào nút "+ Thêm dự án", như bạn có thể thấy bên dưới:

Bảng điều khiển Firebase

Làm theo các bước trên màn hình để hoàn tất việc tạo dự án.

Trong mỗi dự án Firebase, bạn có thể tạo các ứng dụng khác nhau: dành cho Android, iOS, Web, Flutter và Unity. Chọn tùy chọn Android, như bạn thấy ở đây:

Tổng quan về dự án Firebase

Sau đó làm theo các bước sau:

  1. Nhập com.example.makeitso làm tên gói và nhập biệt hiệu (tùy ý). Đối với lớp học lập trình này, bạn không cần thêm chứng chỉ ký gỡ lỗi.
  2. Nhấp vào Tiếp theo để đăng ký ứng dụng của bạn và truy cập tệp cấu hình Firebase.
  3. Nhấp vào Tải xuống google-services.json để tải xuống tệp cấu hình của bạn và lưu nó vào thư mục make-it-so-android/app .
  4. Bấm tiếp . Vì SDK Firebase đã được bao gồm trong tệp build.gradle trong dự án mẫu nên hãy nhấp vào Tiếp theo để chuyển sang các bước tiếp theo .
  5. Nhấn Continue ra console để hoàn tất.

Để làm cho ứng dụng Make it So hoạt động bình thường, có hai điều bạn cần thực hiện trong Bảng điều khiển trước khi chuyển sang mã: bật nhà cung cấp xác thực và tạo cơ sở dữ liệu Firestore. Đầu tiên chúng ta hãy kích hoạt Authentication để người dùng có thể đăng nhập vào ứng dụng:

  1. Từ menu Xây dựng , chọn Xác thực rồi nhấp vào Bắt đầu .
  2. Từ thẻ Phương thức đăng nhập , chọn Email/Mật khẩu và kích hoạt nó.
  3. Tiếp theo, nhấp vào Thêm nhà cung cấp mới rồi chọn và bật Ẩn danh .

Tiếp theo, thiết lập Firestore. Bạn sẽ sử dụng Firestore để lưu trữ các tác vụ của người dùng đã đăng nhập. Mỗi người dùng sẽ nhận được tài liệu riêng của họ trong bộ sưu tập cơ sở dữ liệu.

  1. Từ menu Xây dựng , chọn Firestore , sau đó nhấp vào Tạo cơ sở dữ liệu .
  2. Luôn bật Bắt đầu ở chế độ sản xuất và nhấp vào Tiếp theo .
  3. Khi được nhắc, hãy chọn vị trí lưu trữ dữ liệu Cloud Firestore của bạn. Khi phát triển một ứng dụng sản xuất, bạn sẽ muốn ứng dụng này nằm trong khu vực gần với phần lớn người dùng của mình và có điểm chung với các dịch vụ Firebase khác, như Functions. Đối với lớp học lập trình này, bạn có thể giữ lại khu vực mặc định hoặc chọn khu vực gần bạn nhất.
  4. Nhấp vào Bật để cung cấp cơ sở dữ liệu Firestore của bạn.

Hãy dành chút thời gian để xây dựng Quy tắc bảo mật mạnh mẽ cho cơ sở dữ liệu Firestore. Mở bảng điều khiển Firestore và chuyển đến tab Quy tắc . Sau đó cập nhật Quy tắc bảo mật để trông như thế này:

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

Về cơ bản, các quy tắc này nói rằng bất kỳ người dùng ứng dụng nào đã đăng nhập đều có thể tạo tài liệu cho chính họ trong bất kỳ bộ sưu tập nào. Sau đó, sau khi được tạo, chỉ người dùng đã tạo tài liệu đó mới có thể xem, cập nhật hoặc xóa tài liệu đó.

Chạy ứng dụng

Bây giờ bạn đã sẵn sàng để chạy ứng dụng! Mở thư mục make-it-so-android/start trong Android Studio và chạy ứng dụng (có thể thực hiện việc này bằng Trình mô phỏng Android hoặc thiết bị Android thực).

3. Xác thực Firebase

Bạn sẽ thêm tính năng nào?

Ở trạng thái hiện tại của ứng dụng mẫu Make It So , người dùng có thể bắt đầu sử dụng ứng dụng mà không cần phải đăng nhập trước. Nó sử dụng xác thực ẩn danh để đạt được điều này. Tuy nhiên, tài khoản ẩn danh không cho phép người dùng truy cập dữ liệu của họ trên các thiết bị khác hoặc thậm chí trong các phiên sau. Mặc dù xác thực ẩn danh rất hữu ích cho quá trình làm quen nồng nhiệt nhưng bạn phải luôn cung cấp tùy chọn để người dùng chuyển đổi sang hình thức đăng nhập khác. Với suy nghĩ này, trong lớp học lập trình này, bạn sẽ thêm xác thực email và mật khẩu vào ứng dụng Make It So.

Đã đến lúc viết mã!

Ngay sau khi người dùng tạo tài khoản, bằng cách nhập email và mật khẩu, bạn cần yêu cầu API xác thực Firebase cấp thông tin xác thực email, sau đó liên kết thông tin xác thực mới với tài khoản ẩn danh. Mở tệp AccountServiceImpl.kt trong Android Studio và cập nhật hàm linkAccount để nó trông giống như sau:

mô hình/dịch vụ/impl/AccountServiceImpl.kt

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

Bây giờ hãy mở SignUpViewModel.kt và gọi hàm dịch vụ linkAccount bên trong khối launchCatching của hàm onSignUpClick :

màn hình/sign_up/SignUpViewModel.kt

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

Đầu tiên, nó cố gắng xác thực và nếu cuộc gọi thành công, nó sẽ chuyển sang màn hình tiếp theo ( SettingsScreen ). Khi bạn đang thực hiện các lệnh gọi này bên trong khối launchCatching , nếu xảy ra lỗi ở dòng đầu tiên, ngoại lệ sẽ bị bắt và xử lý, còn dòng thứ hai sẽ không liên lạc được.

Ngay sau khi SettingsScreen được mở lại, bạn cần đảm bảo rằng các tùy chọn Đăng nhậpTạo tài khoản đã biến mất vì hiện tại người dùng đã được xác thực. Để thực hiện việc này, hãy làm cho SettingsViewModel lắng nghe trạng thái của người dùng hiện tại (có sẵn trong AccountService.kt ), để kiểm tra xem tài khoản có ẩn danh hay không. Để làm như vậy, hãy cập nhật uiState trong SettingsViewModel.kt trông giống như sau:

màn hình/cài đặt/SettingsViewModel.kt

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

Điều cuối cùng bạn cần làm là cập nhật uiState trong SettingsScreen.kt để thu thập các trạng thái do SettingsViewModel phát ra:

màn hình/cài đặt/SettingsScreen.kt

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

Bây giờ mỗi khi người dùng thay đổi, SettingsScreen sẽ tự sắp xếp lại để hiển thị các tùy chọn theo trạng thái xác thực mới của người dùng.

Thời gian để kiểm tra!

Chạy Make it So và điều hướng đến cài đặt bằng cách nhấp vào biểu tượng bánh răng ở góc trên cùng bên phải của màn hình. Từ đó, nhấp vào tùy chọn tạo tài khoản:

Màn hình cài đặt Make it SoMàn hình đăng ký Make it So đăng ký

Nhập email hợp lệ và mật khẩu mạnh để tạo tài khoản của bạn. Nó sẽ hoạt động và bạn sẽ được chuyển hướng đến trang cài đặt, nơi bạn sẽ thấy hai tùy chọn mới: đăng xuất và xóa tài khoản của mình. Bạn có thể kiểm tra tài khoản mới được tạo trong bảng điều khiển Xác thực trên bảng điều khiển Firebase bằng cách nhấp vào tab Người dùng.

4. Cửa hàng đám mây

Bạn sẽ thêm tính năng nào?

Đối với Cloud Firestore, bạn sẽ thêm một trình nghe vào bộ sưu tập Firestore lưu trữ các tài liệu đại diện cho các tác vụ được hiển thị trong Make it So. Sau khi thêm trình nghe này, bạn sẽ nhận được mọi cập nhật được thực hiện cho bộ sưu tập này.

Đã đến lúc viết mã!

Cập nhật Flow có sẵn trong StorageServiceImpl.kt trông như thế này:

mô hình/dịch vụ/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()
      }

Mã này đang thêm trình nghe vào bộ sưu tập tác vụ dựa trên user.id . Mỗi tác vụ được thể hiện bằng một tài liệu trong bộ sưu tập có tên tasks và mỗi tác vụ trong số chúng có một trường có tên userId . Xin lưu ý rằng một Flow mới sẽ được phát ra nếu trạng thái của currentUser thay đổi (ví dụ: bằng cách đăng xuất).

Bây giờ bạn cần làm cho Flow trong TasksViewModel.kt phản ánh giống như trong dịch vụ:

màn hình/tác vụ/TasksViewModel.kt

val tasks = storageService.tasks

Và điều cuối cùng sẽ là tạo composable function trong TasksScreens.kt , đại diện cho giao diện người dùng, nhận biết luồng này và thu thập nó dưới dạng trạng thái. Mỗi khi trạng thái thay đổi, hàm có khả năng kết hợp sẽ tự động kết hợp lại và hiển thị trạng thái gần đây nhất cho người dùng. Thêm phần này vào TasksScreen composable function :

màn hình/nhiệm vụ/Nhiệm vụScreen.kt

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

Sau khi hàm có khả năng kết hợp có quyền truy cập vào các trạng thái này, bạn có thể cập nhật LazyColumn (là cấu trúc bạn sử dụng để hiển thị danh sách trên màn hình) trông như thế này:

màn hình/nhiệm vụ/Nhiệm vụScreen.kt

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

Thời gian để kiểm tra!

Để kiểm tra xem nó có hoạt động hay không, hãy thêm một tác vụ mới bằng ứng dụng (bằng cách nhấp vào nút thêm ở góc dưới cùng bên phải của màn hình). Sau khi bạn hoàn tất việc tạo tác vụ, tác vụ đó sẽ xuất hiện trong bộ sưu tập Firestore trong Bảng điều khiển Firestore. Nếu bạn đăng nhập vào Make it So trên các thiết bị khác có cùng tài khoản, bạn sẽ có thể chỉnh sửa các mục việc cần làm của mình và xem chúng được cập nhật trên tất cả các thiết bị trong thời gian thực.

5. Giám sát hiệu suất

Bạn sẽ thêm tính năng nào?

Hiệu suất là điều rất quan trọng cần chú ý vì người dùng rất có thể từ bỏ việc sử dụng ứng dụng của bạn nếu hiệu suất không tốt và họ mất quá nhiều thời gian để hoàn thành một tác vụ đơn giản khi sử dụng ứng dụng đó. Đó là lý do tại sao đôi khi việc thu thập một số số liệu về hành trình cụ thể mà người dùng thực hiện trong ứng dụng của bạn lại rất hữu ích. Và để giúp bạn thực hiện điều đó, Giám sát hiệu suất Firebase cung cấp các dấu vết tùy chỉnh . Thực hiện theo các bước tiếp theo để thêm dấu vết tùy chỉnh và đo lường hiệu suất trong các đoạn mã khác nhau trong Make it So .

Đã đến lúc viết mã!

Nếu mở tệp Performance.kt , bạn sẽ thấy một hàm nội tuyến có tên là trace. Hàm này gọi API giám sát hiệu suất để tạo dấu vết tùy chỉnh, chuyển tên dấu vết dưới dạng tham số. Tham số khác mà bạn thấy là khối mã mà bạn muốn theo dõi. Số liệu mặc định được thu thập cho mỗi dấu vết là thời gian cần thiết để chạy hoàn toàn:

mô hình/dịch vụ/Performance.kt

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

Bạn có thể chọn phần nào của cơ sở mã mà bạn cho là quan trọng để đo lường và thêm dấu vết tùy chỉnh vào đó. Dưới đây là ví dụ về cách thêm dấu vết tùy chỉnh vào hàm linkAccount mà bạn đã thấy trước đó (trong AccountServiceImpl.kt ) trong lớp học lập trình này:

mô hình/dịch vụ/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()
  }

Bây giờ đến lượt bạn! Thêm một số dấu vết tùy chỉnh vào ứng dụng Make it So và chuyển sang phần tiếp theo để kiểm tra xem nó có hoạt động như mong đợi hay không.

Thời gian để kiểm tra!

Sau khi bạn hoàn tất việc thêm dấu vết tùy chỉnh, hãy chạy ứng dụng và đảm bảo sử dụng các tính năng bạn muốn đo lường một vài lần. Sau đó đi tới bảng điều khiển Firebase và đi tới bảng điều khiển Hiệu suất . Ở cuối màn hình, bạn sẽ tìm thấy ba tab: Yêu cầu mạng , Dấu vết tùy chỉnhHiển thị màn hình .

Chuyển đến tab Dấu vết tùy chỉnh và kiểm tra xem dấu vết bạn đã thêm trong cơ sở mã có được hiển thị ở đó không và bạn có thể biết thường mất bao nhiêu thời gian để thực thi các đoạn mã này.

6. Cấu hình từ xa

Bạn sẽ thêm tính năng nào?

Có vô số trường hợp sử dụng Cấu hình từ xa, từ việc thay đổi giao diện ứng dụng của bạn từ xa đến định cấu hình các hành vi khác nhau cho các phân khúc người dùng khác nhau. Trong lớp học lập trình này, bạn sẽ sử dụng Cấu hình từ xa để tạo một nút chuyển đổi tính năng sẽ hiển thị hoặc ẩn tính năng tác vụ chỉnh sửa mới trên ứng dụng Make it So.

Đã đến lúc viết mã!

Điều đầu tiên bạn cần làm là tạo cấu hình trong bảng điều khiển Firebase. Để làm như vậy, bạn cần điều hướng đến bảng điều khiển Cấu hình từ xa và nhấp vào nút Thêm tham số . Điền vào các trường theo hình ảnh bên dưới:

Cấu hình từ xa Tạo hộp thoại tham số

Khi tất cả các trường đã được điền, bạn có thể nhấp vào nút Lưu và sau đó Xuất bản . Bây giờ, tham số đã được tạo và có sẵn cho cơ sở mã của bạn, bạn cần thêm mã sẽ tìm nạp các giá trị mới cho ứng dụng của mình. Mở tệp ConfigurationServiceImpl.kt và cập nhật cách triển khai 2 chức năng này:

mô hình/dịch vụ/impl/ConfigurationServiceImpl.kt

override suspend fun fetchConfiguration(): Boolean {
  return remoteConfig.fetchAndActivate().await()
}

override val isShowTaskEditButtonConfig: Boolean
  get() = remoteConfig[SHOW_TASK_EDIT_BUTTON_KEY].asBoolean()

Hàm đầu tiên tìm nạp các giá trị từ máy chủ và được gọi ngay khi ứng dụng khởi động, trong SplashViewModel.kt . Đó là cách tốt nhất để đảm bảo rằng các giá trị cập nhật nhất sẽ có sẵn trên tất cả các màn hình ngay từ đầu. Đó không phải là trải nghiệm người dùng tốt nếu bạn thay đổi giao diện người dùng hoặc hành vi của ứng dụng sau này, khi người dùng đang làm một việc gì đó!

Hàm thứ hai trả về giá trị boolean đã được xuất bản cho tham số bạn vừa tạo trong Bảng điều khiển. Và bạn sẽ cần truy xuất thông tin này trong TasksViewModel.kt , bằng cách thêm thông tin sau vào hàm loadTaskOptions :

màn hình/tác vụ/TasksViewModel.kt

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

Bạn đang truy xuất giá trị trên dòng đầu tiên và sử dụng giá trị đó để tải các tùy chọn menu cho các mục nhiệm vụ trên dòng thứ hai. Nếu giá trị là false , điều đó có nghĩa là menu sẽ không chứa tùy chọn chỉnh sửa. Bây giờ bạn đã có danh sách các tùy chọn, bạn cần làm cho giao diện người dùng hiển thị chính xác. Khi xây dựng một ứng dụng bằng Jetpack Compose, bạn cần tìm hàm composable function khai báo giao diện người dùng của TasksScreen sẽ trông như thế nào. Vì vậy hãy mở file TasksScreen.kt và cập nhật LazyColum để trỏ đến các tùy chọn có sẵn trong TasksViewModel.kt :

màn hình/nhiệm vụ/Nhiệm vụScreen.kt

val options by viewModel.options

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

TaskItem là một composable function khác khai báo giao diện người dùng của một tác vụ đơn lẻ sẽ trông như thế nào. Và mỗi tác vụ đều có một menu với các tùy chọn được hiển thị khi người dùng nhấp vào biểu tượng ba chấm ở cuối tác vụ đó.

Thời gian để kiểm tra!

Bây giờ bạn đã sẵn sàng để chạy ứng dụng! Kiểm tra xem giá trị bạn đã xuất bản bằng bảng điều khiển Firebase có khớp với hoạt động của ứng dụng hay không:

  • Nếu false , bạn chỉ thấy hai tùy chọn khi nhấp vào biểu tượng ba chấm;
  • Nếu true , bạn sẽ thấy ba tùy chọn khi nhấp vào biểu tượng ba chấm;

Hãy thử thay đổi giá trị một vài lần trong Bảng điều khiển và khởi động lại ứng dụng. Thật dễ dàng để khởi chạy các tính năng mới trong ứng dụng của bạn bằng Cấu hình từ xa!

7. Xin chúc mừng

Xin chúc mừng, bạn đã xây dựng thành công ứng dụng Android với Firebase và Jetpack Compose!

Bạn đã thêm Xác thực Firebase, Giám sát hiệu suất, Cấu hình từ xa và Cloud Firestore vào một ứng dụng Android được xây dựng hoàn toàn bằng Jetpack Compose cho giao diện người dùng và bạn đã làm cho ứng dụng này phù hợp với kiến ​​trúc MVVM được đề xuất!

đọc thêm

Tài liệu tham khảo