Android

Firebase, Bài 2.3: Giới thiệu về Realtime Database.

Sau khi đã làm quen với các Value Events xong thì hôm nay chúng ta sẽ “đổ bộ” sang các Child Events. Thực tế thì các Child Events cũng là các Value Events, vì cấu trúc của Firebase Realtime Database là dạng Object trong Object. Các children luôn nằm trong 1 object – mà object đó lại chính là value của một object lớn hơn. Tuy nhiên, các Child Events đi sâu về nội dung và số lượng của các children chứ không chỉ đơn thuần là nội dung của parent object.

6. Các Child Events trong Firebase Realtime Database

Firebase cung cấp cho chúng ta 4 loại Child Events, bao gồm Child_Added, Child_Changed, Child_MovedChild_Removed. Bài viết dưới đây dựa theo hướng dẫn của anh David East, một kĩ sư cao cấp trụ cột của Firebase Team At Google.

FirebaseRealtimeDatabase

Trước khi bắt đầu thì chúng ta hãy nhìn lại phần cơ sở dữ liệu “huyền thoại” mà tôi đã dùng để minh họa ngày hôm trước. Và nếu bạn chưa tìm hiểu về các bài viết trước về Firebase, Firebase Authentication và Firebase Realtime Database của chúng tôi thì bây giờ là lúc các bạn nên làm điều đó. Các biến myRef và ref ở bên dưới được định nghĩa giống như trong bài viết trước.FirebaseRealtimeDatabase-Example

Như tôi đã nói, Firebase cung cấp cho chúng ta các Child_Added, Child_Changed, Child_Moved và Child_Removed Events. Cho dù các hàm trong thư viện Firebase* cho Android, FIR* cho iOS hay firebase.* cho Web được đặt tên theo kiểu “nhập gia tùy tục” cho phù hợp với phong cách viết code của ngôn ngữ và nền tảng đích, thì 4 cái tên trên không hề thay đổi vì đó là bản chất chung, vd ta có các hàm onChildAdded() cho Java/Android, observe(.childAdded, …) cho Swift/iOS hay on(“child_added”, …) cho JS/Web để chỉ Child_Added_Event. Lưu ý là các children được sắp xếp theo thứ tự chữ cái theo các key, tức là các “KI2”, không phải theo thứ tự thời gian bạn thêm vào. Vd bạn muốn thêm 1 child mới có key là “-Abc213569xYZ” vào cùng tần với các children kia,  thì tự dưng nó sẽ được nhảy lên đầu danh sách, ngay dưới b797bdd4 mặc dù nó chỉ mới xuất hiện sau này.

Bấy giờ, ta sẽ trỏ vào node users/users/b797bdd4-…/, hiện tại thì ta đang có 4 children, bao gồm -KI2GLhv…, -KI2Gli…, -KI2H2r…, -KI2q6K… Lưu ý là 4 children này nằm trong 1 Object và Object này chính là value của b797bdd4, không phải tách rời hoàn toàn ra khỏi value object kia. Khi có 1 Child Event thì đương nhiên sẽ có 1 Value Event xảy ra. Do đó, nếu bạn đặt luôn cả Value Event và Child Event cho cùng 1 node dữ liệu thì sẽ có 2 lần listen/observe xảy ra, và nếu bạn xử lí không khéo thì có thể sẽ bị trùng. Và nếu bạn đủ trình thì vẫn có thể dùng ValueEvent để giải quyết vấn đề mà không “thèm” dùng Child Events để “cho nó máu”. Nhưng tốt hơn thì cứ dùng Child Event cho đơn giản.

  • Một Child_Added Event được gọi khi trong một value object xuất hiện thêm 1 child mới. Chẳng hạn như cho thêm một Object mới vào node đó, thì nó sẽ ngang hàng với các children đã có sẵn, thì Firebase sẽ lập tức gửi một Child_Added Event xuống các thiết bị đang “lắng nghe”(Android, Web) hoặc “quan sát” (Swift, iOS) sự thay đổi tại node đó, bao gồm cả về Value Event vẫn Child Event. Tất nhiên, chúng ta sẽ chỉ tập trung vào Child Event mà thôi. Trong Firebase Console phần Database, thì Event này được thể hiện với màu xanh lá.
  • Một Child_Changed Event được gọi khi một trong các child đã tồn tại có sự thay đổi về value, và sự thay đổi này có thể nằm bất cứ nơi nào trong value object của child đó. Vd trong child KI2GLh (thứ nhất), có sự thay đổi, chẳng hạn như fieldName bị đổi thành “anotherMessage”, hay text được sửa thành “this is my last message”, hay thậm chí là xuất hiện thêm 1 trường mới là number, hoặc trường text bị loại bỏ, thì Firebase sẽ lập tức gửi Child_Changed Event xuống các thiết bị đang kết nối vào node đó. Do đó, Event được gọi không chỉ có sự thay đổi về nội dung của các children bên trong value object của 1 child bất kì, mà còn là số lượng các children bên trong value object đó. Trong Firebase Console phần Database, thì Event này được thể hiện với màu vàng.
  • Một Child_Moved Event được gọi khi một trong các child đã tồn tại có sự di chuyển từ vị trí này sang vị trí khác, và nguyên nhân phổ biến nhất là do bạn thay đổi phần key của child đó, chẳng hạn như bạn muốn sắp xếp lại các children lại theo thứ tự bảng chữ cái theo một property nào đó trong các children. Bạn có thể xử lí trực tiếp Event này, hoặc gián tiếp thông qua Child_Changed Event vẫn được. Tuy nhiên, cá nhân tôi không sắp xếp lại các children ngay trên Firebase Database, mà thường để dành việc xử lí cho thiết bị khách truy cập CSDL. Trong Firebase Console phần Database, thì Event này được thể hiện với màu xanh dương.
  • Một Child_Removed Event được gọi khi một child được xóa đi, và như bạn đã biết, xóa một child sẽ xóa luôn tất cả các nội dung bên trong đó. Trong Firebase Console phần Database, thì Event này được thể hiện với màu đỏ.

7. Viết code xử lí các Child Event

Bấy giờ là lúc thao tác với code. Và tôi đưa ra code theo CSDL ví dụ của chúng ta. Dưới đây là các code trích ngang, không phải code hoàn chỉnh.

7.1. Đối với Android (với myRef được định nghĩa như trong bài trước, sẽ trỏ vào “b797bdd4-“)

FirebaseRealtimeDatabase-Example

7.2. Đối với iOS – Swift (với ref được định nghĩa như trong bài trước, sẽ trỏ vào “b797bdd4-“)

FirebaseRealtimeDatabase-Example

7.3. Đối với Web (với ref được định nghĩa như trong bài trước, sẽ trỏ vào “b797bdd4-“)

FirebaseRealtimeDatabase-Example

7. Bỏ các listeners/observers

Để dừng các hoạt động “lắng nghe” hoặc “quan sát”, thì bạn chỉ đơn giản gắn hàm removeEventListener() trong Android, removeObserverWithHandle (nếu bạn muốn làm FIRDatabaseHandle) hoặc removeAllObservers với iOS, hay đơn giản chỉ là off() khi làm Web, vào myRef hoặc ref là được. Tuy nhiên, điều này cũng không quá cần thiết sau khi user sign out và màn hình sẽ trả về một Activity khác, hay một ViewController khác, hay một trang HTML khác có code xử lí và gắn kết Authentication và Realtime Database.

8. Dữ liệu ngoại tuyến

Firebase có cung cấp việc lưu lại một phần dữ liệu trên thiết bị di động để sử dụng khi offline. Bạn có thể cho phép người dùng thêm, sửa hoặc xóa các dữ liệu ngoại tuyến, và khi thiết bị có kết nối trở lại, thì dữ liệu sẽ lại được đồng bộ lên CSDL gốc. Lưu ý là về mặc định thì tính năng này bị tắt, do đó bạn phải tự bật. Để yêu cầu “Hey project, mày lưu lại dữ liệu Firebase Database offline cho tao nhé!” thì bạn sẽ gán FirebaseDatabase#setPersistenceEnabled(boolean enable) với Android hoặc FIRDatabase#persistenceEnabled = enable với iOS/Swift, với giá trị enabletrue để lưu dữ liệu, còn false đương nhiên là không lưu, vào instance của FirebaseDatabase hay FIRDatabase, không phải myRef hay ref nhé.

Đối với web thì Firebase không đưa ra cách giải quyết vấn đề offline, bởi “phải có internet thì mới dùng được ứng dụng web chứ!”. Tuy nhiên, nếu bạn muốn làm một Chrome hay Firefox extension thì đương nhiên, offline data là điều cần phải có. Cá nhân tôi đề xuất giải pháp “bánh quy”, tức là dùng cookies để lưu lại 1 phần dữ liệu. Tất nhiên, có thể bạn sẽ có các cách làm khác hay hơn, tối ưu hơn.

Như vậy, chúng tôi đã giới thiệu sơ lược về Firebase Realtime Database, bao gồm các Value Event và Child Events để các bạn có thể dễ dàng tích hợp Firebase Realtime Database vào ứng dụng của mình cũng như viết code xử lí các Events khi dữ liệu có sự thay đổi. Sắp tới thì tôi sẽ Việt hóa các hướng dẫn của anh David East về việc chuyển đổi từ SQLDatabase sang Firebase Database. Xin lưu ý trước là do bản chất 2 Database trên là hoàn toàn khác nhau, nên sẽ không có một cách chuyển đổi tối ưu và hiệu quả nhất một cách tổng quát, mà bản thân các LTV cần linh hoạt xử lí tùy theo trình độ và kinh nghiệm của mình. Hẹn gặp lại các bạn trong vài ngày tới.

4 thoughts on “Firebase, Bài 2.3: Giới thiệu về Realtime Database.”

    1. Căm ơn bạn rất nhiều. Hi vọng bạn sẽ tiếp tục theo dõi các bài viết mới của EitGuide.

    1. Bạn child vào nó luôn, value sẽ là kiểu (NS)String. Vd với android, bạn có myRef.child(“b7…”).child(“KI2GL…”).child(“text”).addValueEventListener((snapshot) => String text = snapshot.getValue(String.class))

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.