Triển khai Base Flutter - Phần 6: Mở rộng

Firebase

I. Các công việc cần xử lý

Trải qua các phần trên chúng ta đã xây dựng được 1 base khá hoàn chỉnh cho ứng dụng Flutter rồi, nhưng khi làm về Mobile chúng ta còn thường xuyên gặp thêm những việc như: Notification, Analytic, Secure, … Và ở phần này mình sẽ triển khai thêm 1 vài đầu việc quan trọng như:

II. Chi tiết xử lý

1. Firebase và cách cấu hình với nhiều môi trường khác nhau

Khi kết nối với Backend, chúng ta đã có quá nhiều môi trường rồi. Và tương tự khi tích hợp Firebase vào ứng dụng, chúng ta cũng nên tách biệt rõ ràng giữa môi trường prod vs dev. Ở đây mình chỉ triển khai với 2 dạng build:

Để làm được việc này tự động, chúng ta cần phải triển khai trên cả Android và iOS với native code.

Với Android:

Để có thể chuyển đổi firebase ứng với các môi trường prod/dev, hướng sử lý ở đây chính là trước khi project được build chúng ta sẽ triển khai 1 task có thể copy được file google_service.json tương ứng với môi trường prod/dev vào thư mục android/app/src.

Đó là tư tưởng và hướng triển khai, cách làm cụ thể sẽ như sau:


Với iOS:
Cũng với tư tưởng của Android, chúng ta tạo thư mục Firebase chứa GoogleService-Info.plist dev/prod và copy file tương ứng với môi trường.

Trong Build Phases, mình tạo 1 Firebase setup run script và kéo lên trên cho nó chạy đầu:

Nội dung chi tiết:

if [ "${CONFIGURATION}" == "Release" ]; then
cp -r "${PROJECT_DIR}/Runner/Firebase/GoogleService-Info-PROD1.plist" "${PROJECT_DIR}/Runner/GoogleService-Info.plist"
echo "Production GoogleService-Info.plist copied"
elif [ "${CONFIGURATION}" == "Debug" ]; then
cp -r "${PROJECT_DIR}/Runner/Firebase/GoogleService-Info-IDA.plist" "${PROJECT_DIR}/Runner/GoogleService-Info.plist"
echo "IDA GoogleService-Info.plist copied”
fi

2. Xử lý state toàn ứng dụng và triển khai Dependency injection (DI)

Dependency Injection (DI) là một nguyên tắc trong phát triển phần mềm và thiết kế kiến trúc để quản lý các phụ thuộc (dependencies) giữa các thành phần trong ứng dụng một cách dễ dàng. Ở trong base mình sẽ sử dụng nó để quản lý các phụ thuộc về:

Các đối tượng về dio, service, repositories, use case mình sử dụng DI để cấu hình sự phụ thuộc và khi cần có thể truy cập được ngay để sử dụng.

Còn state toàn ứng dụng là gì? Chắc hẳn các bạn cũng đã từng gặp nhiều trường hợp tương tự như thế này: Thông tin cá nhân người dùng sau khi đăng nhập có tên, ngày sinh, avatar, … Phần thông tin này được hiển thị ở rất nhiều nơi trên ứng dụng, nào là trang chủ hiện avatar và tên, nào là trang cá nhân cũng hiện đủ thông tin,... Và chúng ta có 1 nút để thực hiện việc cập nhật thông tin cá nhân đó. Mặc nhiên tất cả những nơi đang hiển thị dữ liệu cũng cần phải update theo phải không? Và với những dữ liệu như này mình hay gọi là global state. Để có được dữ liệu lưu trữ thông tin user kia, mình có 1 AuthCubit với AuthState tương ứng và sử dụng DI để tạo singleton cho nó, các thành phần giao diện cần sử dụng thông tin của user có thể thêm BlocProvider với value chính là singleton AuthCubit.

3. Một vài vấn đề về securities

Vấn đề securities thì rất là rộng, nhưng khi làm App rất nhiều người lưu trữ thông tin không an toàn ví dự như lưu trữ token, refresh-token vào bộ nhớ SharedPreferences. Chúng ta có thể làm tốt hơn khi lưu trữ các thông tin nhạy cảm vào 1 bộ nhớ được mã hóa (keystore/keychain)

4. Tích hợp Sentry để phát hiện lỗi dễ dàng

Ứng dụng đẩy lên prod và tiếp cận tới hàng ngàn người, lúc này có vô số các bug tiềm tàng mà trong quá trình phát triển chúng ta đã bỏ qua, việc tích hợp sentry để bắt được các lỗi trên là rất tiện lợi. Chúng ta cũng nên chia rõ giữa sentry môi trường prod vs dev ra nhé.

5. Tuân thủ lint để code sạch hơn

Dự án có rất nhiều người cùng xây dựng, để thống nhất theo 1 style thì việc thêm nhiều rules trong lint để mọi người cùng tuân thủ là 1 điều tốt và nên làm nha.

III. Tổng kết

Như vậy, trải qua 4 phần chính, chúng ta đã xây được 1 base tương đối hoàn thiện. Rất vui khi được các bạn đồng hành tới tận đây, mình cũng mới chuyển sang làm với Flutter nên có thể còn nhiều thiếu sót, mong nhận được sự góp ý từ mọi người.

Mình cảm ơn!