How to use Snapshot listener to get real time upda

2020-06-27 03:02发布

问题:

Below is the code I used to retrieve documents data in a recyclerview. It works fine. But whenever the new document is added, it does not update it in real time. I know snapshot listener is for that purpose only but having a hard time to get it work. Any help will be appreciated. :)

 mFirestore.collection("Users").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
            @Override
            public void onComplete(@NonNull Task<QuerySnapshot> task) {
                if (task.isSuccessful()){
                    for (DocumentSnapshot document : task.getResult()) {
                        Message message = document.toObject(Message.class);
                        messageList.add(message);
                        mAdapter.notifyDataSetChanged();
                    }
                }
            }
        });

回答1:

you should separate the snapshot event like this.. then you can easily find out, what's the problem

mFirestore.collection("Users")
        .addSnapshotListener(new EventListener<QuerySnapshot>() {
            @Override
            public void onEvent(@Nullable QuerySnapshot snapshots,
                                @Nullable FirebaseFirestoreException e) {
                if (e != null) {
                    Log.w("TAG", "listen:error", e);
                    return;
                }

                for (DocumentChange dc : snapshots.getDocumentChanges()) {
                    switch (dc.getType()) {
                        case ADDED:
                            Log.d("TAG", "New Msg: " + dc.getDocument().toObject(Message.class));
                            break;
                        case MODIFIED:
                            Log.d("TAG", "Modified Msg: " + dc.getDocument().toObject(Message.class));
                            break;
                        case REMOVED:
                            Log.d("TAG", "Removed Msg: " + dc.getDocument().toObject(Message.class));
                            break;
                    }
                }

            }
        });

Maybe the snapshot you got, was triggered by [MODIFIED] event, not [ADDED]..



回答2:

Please see how to use it in recycler view:

// Get Chats List From FireStore
private void getChatListFromFireBase(String hiddenStatus) {

    lIndividualChatList = new ArrayList<>();
    lIndividualChatListIds = new ArrayList<>();

    lIndividualChatList.clear();
    lIndividualChatListIds.clear();

    fbFs.collection("individual_chats")
        .document(mySqlUserId)
        .collection("lists")
        .addSnapshotListener(new EventListener<QuerySnapshot>() {
            @Override
            public void onEvent(QuerySnapshot documentSnapshots,
                                FirebaseFirestoreException e) {

                if (e != null) {

                }

                for (DocumentChange dc : documentSnapshots.getDocumentChanges()) {
                    switch (dc.getType()) {
                        case ADDED:

                            key = dc.getDocument()
                                    .getId();

                            firebaseRetrofitQuery(dc,
                                                  "Added",
                                                  key);

                            break;
                        case MODIFIED:

                            key = dc.getDocument()
                                    .getId();

                            // Do The Change Function
                            firebaseRetrofitQuery(dc,
                                                  "Changed",
                                                  key);

                            break;
                        case REMOVED:

                            break;
                    }
                }

            }
        });
}



// FireBase And Retrofit Query
private void firebaseRetrofitQuery(DocumentChange documentChange,
                                   final String childActivityType,
                                   final String key) {

    if (childActivityType.equals("Added")) {

        lIndividualChatListIds.add(key);

    }

    // Get The Receiver Id To Get Data From Other Nodes
    final String mySqlFriendUserId = documentChange.getDocument()
                                                   .getId();

    final String hideStatus = (String) documentChange.getDocument()
                                                     .getData()
                                                     .get("hide_status");

    if (childActivityType.equals("Added")) {

        // Populate The Array List With Data From Both Nodes
        lIndividualChatList.add(new IndividualListModel(mySqlFriendUserId,
                                                        hideStatus));

    }

    if (childActivityType.equals("Changed")) {

        int index = lIndividualChatListIds.indexOf(key);
        lIndividualChatList.set(index,
                                new IndividualListModel(mySqlFriendUserId,
                                                        hideStatus));

    }

    // Use The Adapter To Populate The Recycler View
    aIndividualChatList = new IndividualListAdapter(getContext(),
                                                    lIndividualChatList,
                                                    senderActivity,
                                                    new IndividualListAdapter.OnItemClickListener() {

                                                        @Override
                                                        public void onItemClicked(final Map data) {

                                                        }
                                                    });
    rvList.setAdapter(aIndividualChatList);

    aIndividualChatList.notifyDataSetChanged();

}


回答3:

If you want to keep listening your Firestore data (realtime update), you should do like this:

mFirestore.collection("Users")
            .addSnapshotListener(new EventListener<QuerySnapshot>() {
                @Override
                public void onEvent(@Nullable QuerySnapshot queryDocumentSnapshots,
                                    @Nullable FirebaseFirestoreException e) {

                    if (e != null) {
                        Log.w("YourTag", "Listen failed.", e);
                        return;
                    }

                    for (QueryDocumentSnapshot doc : queryDocumentSnapshots) {
                        if (doc.exists()){
                            Message message = doc.toObject(Message.class);
                            messageList.add(message);
                            mAdapter.notifyDataSetChanged();
                        }
                    }
                    Log.d("YourTag", "messageList: " + messageList);
                }
            });

the way you use only retrieve Firestore data once.

Check this >> https://firebase.google.com/docs/firestore/query-data/listen