Android FirebaseUI for Cloud Firestore - FirestoreRecyclerAdapter
根據上一篇 FireStore 文章的延伸, 今天這篇打算分享 FirestoreRecyclerAdapter,FirestoreRecyclerAdapter 是 FirebaseUI-Android 的其中一個部分的工具,在學習 firestore 發現這個東西非常好用,順便自己做個筆記用途,如有錯誤的地方,敬請留言告知。
不用擔心,FirebaseUI會自動為您完成所有這些操作!
首先,通過構建配置適配器 FirestoreRecyclerOptions 。在這種情況下,我們將繼續我們的電話簿範例:
如果您不想手動啟動/停止收聽,您可以使用 Android架構組件自動管理生命週期 FirestoreRecyclerAdapter 。傳遞 LifecycleOwner 給 FirestoreRecyclerOptions.Builder#setLifecycleOwner(...) 和,FirebaseUI將自動開始和停止收聽 onStart() 和 onStop() 。
該 FirestorePagingAdapter 是建立在頂部的Android分頁支持庫。在應用程序中使用適配器之前,必須在支持庫上添加依賴項:
以下兩點跟上述的 FirestoreRecyclerAdapter ㄧ樣
物件模型
public class Contact {
private String name;
private String email;
private String phone;
private int priority;
public Contact() {
// Empty construtor needed
}
public Contact(String name, String email, String phone) {
this.name = name;
this.email = email;
this.phone = phone;
}
public Contact(String name, String email, String phone, int priority) {
this.name = name;
this.email = email;
this.phone = phone;
this.priority = priority;
}
public String getName() {
return name;
}
public String getEmail() {
return email;
}
public String getPhone() {
return phone;
}
public int getPriority() {
return priority;
}
}
關於這個模型類的一些注意事項:- getter和setter遵循JavaBean命名模式,允許Firestore將數據映射到字段名稱(例如: getName() 提供 name 字段)。
- 該類有一個空構造函數,這是Firestore自動數據映射所必需的。
對於正確構造的模型類(如Contact上面的類),Firestore可以執行自動序列化 DocumentReference#set() 和自動反 序列化 DocumentSnapshot#toObject() 。有關Firestore中數據映射的詳細信息,請參閱有關自定義對象的文檔。
Querying
這個 Class 主要用來查詢,在應用的主屏幕上,您可能希望顯示50條最新的聊天消息,排列順序依照 priority 欄位,升冪或降冪拍序。在Firestore中,您將使用以下查詢:Query query = FirebaseFirestore.getInstance()
.collection("PhoneBook")
.orderBy("priority", Query.Direction.ASCENDING)
.limit(50);
要在沒有FirebaseUI的情況下檢索此數據,您可以使用addSnapshotListener偵聽實時查詢更新:
query.addSnapshotListener(new EventListener<QuerySnapshot>() {
@Override
public void onEvent(@Nullable QuerySnapshot snapshot,
@Nullable FirebaseFirestoreException e) {
if (e != null) {
// Handle error
//...
return;
}
// Convert query snapshot to a list of chats
List<Contact> contacts = snapshot.toObjects(Contact.class);
// Update UI
// ...
}
});
使用FirebaseUI填充 RecyclerView
如果您正在顯示數據列表,則可能希望將 Contact 對象(這邊使用電話簿,聯絡資料作為範例)綁定到a RecyclerView 。這意味著實現自定義 RecyclerView.Adapter ,並與協調的更新 EventListener 上 Query 。不用擔心,FirebaseUI會自動為您完成所有這些操作!
選擇適配器
FirebaseUI為Cloud Firestore提供兩種類型的RecyclerView適配器:- FirestoreRecyclerAdapter - 將a綁定 Query 到a RecyclerView 並響應所有包含要添加,刪除,移動或更改的項目的實時事件。最好與小結果集一起使用,因為所有結果都會立即加載。
- FirestorePagingAdapter - 通過在頁面中加載數據將a綁定 Query 到a RecyclerView 。最適用於大型靜態數據集。此適配器不會遵守實時事件,因此它不會檢測新的/已刪除的項目或對已加載的項目的更改。
使用 FirestoreRecyclerAdapter
該 FirestoreRecyclerAdapter 綁定 Query 的 RecyclerView 。添加,刪除或更改文檔時,這些更新會自動實時應用於您的UI。首先,通過構建配置適配器 FirestoreRecyclerOptions 。在這種情況下,我們將繼續我們的電話簿範例:
// Configure recycler adapter options:
// * query is the Query object defined above.
// * Chat.class instructs the adapter to convert each DocumentSnapshot to a Chat object
FirestoreRecyclerOptions<Contact> options = new FirestoreRecyclerOptions.Builder<Contact>()
.setQuery(query, Contact.class)
.build();
如果需要自定義解析模型類的方式,可以使用自定義 SnapshotParser :
...setQuery(..., new SnapshotParser<Contact>() {
@NonNull
@Override
public Chat parseSnapshot(@NonNull DocumentSnapshot snapshot) {
return ...;
}
});
接下來創建 FirestoreRecyclerAdapter 對象。您應該已經有一個 ViewHolder 子類來顯示每個項目。在這種情況下,我們將使用自定義 ContactHolder 類:
public class ContactAdapter extends FirestoreRecyclerAdapter<Contact, ContactAdapter.ContactViewHolder> {
public ContactAdapter(@NonNull FirestoreRecyclerOptions<Contact> options) {
super(options);
}
@Override
protected void onBindViewHolder(@NonNull ContactViewHolder holder, int position, @NonNull Contact model) {
holder.tvName.setText(model.getName());
holder.tvEmail.setText(model.getEmail());
holder.tvPhone.setText(model.getPhone());
holder.tvPriority.setText(String.valueOf(model.getPriority()));
}
@NonNull
@Override
public ContactViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int position) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.contact_item,
viewGroup, false);
return new ContactViewHolder(view);
}
class ContactViewHolder extends RecyclerView.ViewHolder {
TextView tvName;
TextView tvEmail;
TextView tvPhone;
TextView tvPriority;
public ContactViewHolder(@NonNull View itemView) {
super(itemView);
tvName = itemView.findViewById(R.id.tv_name);
tvEmail = itemView.findViewById(R.id.tv_email);
tvPhone = itemView.findViewById(R.id.tv_phone_num);
tvPriority = itemView.findViewById(R.id.tv_priority);
}
}
}
FirestoreRecyclerAdapter lifecycle
開始/停止收聽 @Override
protected void onStart() {
super.onStart();
adapter.startListening();
}
@Override
protected void onStop() {
super.onStop();
adapter.stopListening();
}
自動收聽如果您不想手動啟動/停止收聽,您可以使用 Android架構組件自動管理生命週期 FirestoreRecyclerAdapter 。傳遞 LifecycleOwner 給 FirestoreRecyclerOptions.Builder#setLifecycleOwner(...) 和,FirebaseUI將自動開始和停止收聽 onStart() 和 onStop() 。
FirestoreRecyclerOptions<Contact> options = new FirestoreRecyclerOptions.Builder<Contact>()
.setQuery(query, Contact.class)
.setLifecycleOwner(this)
.build();
數據和錯誤事件
使用時, FirestoreRecyclerAdapter 您可能希望每次數據更改或出現錯誤時執行某些操作。為此,請覆蓋 適配器的 onDataChanged() 和 onError() 方法:FirestoreRecyclerAdapter adapter = new FirestoreRecyclerAdapter<Chat, ChatHolder>(options) {
// ...
@Override
public void onDataChanged() {
// Called each time there is a new query snapshot. You may want to use this method
// to hide a loading spinner or check for the "no documents" state and update your UI.
// ...
}
@Override
public void onError(FirebaseFirestoreException e) {
// Called when there is an error getting a query snapshot. You may want to update
// your UI to display an error message to the user.
// ...
}
};
使用 FirestorePagingAdapter
在 FirestorePagingAdapter 綁定 Query 到 RecyclerView 在頁面加載的文件。這導致時間和內存有效綁定,但是它放棄了由此分配的實時事件 FirestoreRecyclerAdapter 。該 FirestorePagingAdapter 是建立在頂部的Android分頁支持庫。在應用程序中使用適配器之前,必須在支持庫上添加依賴項:
implementation 'android.arch.paging:runtime:1.x.x'
首先,通過構建配置適配器 FirestorePagingOptions 。由於分頁適配器不適合聊天應用程序(它不會檢測新消息),我們將考慮加載泛型的適配器 Item :
// The "base query" is a query with no startAt/endAt/limit clauses that the adapter can use
// to form smaller queries for each page. It should only include where() and orderBy() clauses
Query baseQuery = mItemsCollection.orderBy("value", Query.Direction.ASCENDING);
// This configuration comes from the Paging Support Library
// https://developer.android.com/reference/android/arch/paging/PagedList.Config.html
PagedList.Config config = new PagedList.Config.Builder()
.setEnablePlaceholders(false)
.setPrefetchDistance(10)
.setPageSize(20)
.build();
// The options for the adapter combine the paging configuration with query information
// and application-specific options for lifecycle, etc.
FirestorePagingOptions<Item> options = new FirestorePagingOptions.Builder<Item>()
.setLifecycleOwner(this)
.setQuery(baseQuery, config, Item.class)
.build();
- 如果需要自定義解析模型類的方式,可以使用自定義 SnapshotParser
- 創建 FirestorePagingAdapter 對象。您應該已經有一個 ViewHolder 子類來顯示每個項目。在這種情況下,我們將使用自定義 ItemViewHolder 類
FirestorePagingAdapter 生命週期
以下兩點跟上述的 FirestoreRecyclerAdapter ㄧ樣
- 開始/停止收聽
- 自動收聽
使用時 FirestorePagingAdapter ,您可能希望每次數據更改或出現錯誤時執行某些操作。為此,請覆蓋 onLoadingStateChanged() 適配器的方法:
FirestorePagingAdapter<Item, ItemViewHolder> adapter =
new FirestorePagingAdapter<Item, ItemViewHolder>(options) {
// ...
@Override
protected void onLoadingStateChanged(@NonNull LoadingState state) {
switch (state) {
case LOADING_INITIAL:
// The initial load has begun
// ...
case LOADING_MORE:
// The adapter has started to load an additional page
// ...
case LOADED:
// The previous load (either initial or additional) completed
// ...
case ERROR:
// The previous load (either initial or additional) failed. Call
// the retry() method in order to retry the load operation.
// ...
}
}
};
FirebaseUI for Cloud Firestore
FirebaseUI的其中一小部分介紹完畢。
留言
張貼留言