Using data from Firestore and Firebase RTDB in single RecyclerView

半腔热情 提交于 2019-12-31 07:17:13

问题


I have a RecyclerView which is populated by posts stored in a Firestore database. Each post is written as a document with a unique postID, storing the posted message, a timestamp and a like-counter.

    //mUploads is defined as private List<Upload> mUploads;
    //Upload object stores post message, timestamp and likes      
    mUploads = new ArrayList<>();

    mFireStoreOrdered = mFireStoreInst.collection("posts").orderBy("time");
    mFireStoreOrdered
            .get()
            .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                @Override
                public void onComplete(@NonNull Task<QuerySnapshot> task) {
                    if (task.isSuccessful()) {
                        for (DocumentSnapshot doc : task.getResult()) {

                            //For each document get the ID
                            String postID = doc.getId();

                            // Upload object stores post message, timestamp and likes
                            Upload upload = doc.toObject(Upload.class).withId(postID);

                            mUploads.add(upload);
                        }

                        Collections.reverse(mUploads);

                        //Populate Recyclerview
                        mAdapter = new UploadAdapter(MainActivity.this, mUploads);

                        mContentView.setAdapter(mAdapter);


                    } else {
                        //...
                    }
                }
            });

When trying to implement the "like"-functionality for these posts I got to the limits of Firestore, which can only handle one document update per second.

Reading this article convinced me of using the Firebase Realtime Database to store the likes by using transaction operations instead of using distributed counters. I do not want to display the likes in real-time, I only want to use the RTDB to handle multiple likes/dislikes per second.

When additionally using the Firebase RTDB for likes, I would add data to a path /posts/postID/likes.

How can I get the post messages from Firestore and add the corresponding likes from the RTDB to mUploads before passing it to the adapter. Specificially, is it possible to ensure that I set the correct like value to its corresponding post, without querying for each postID.


回答1:


This is a very common practice when it comes to Firestore, to store the number of likes in the Firebase Realtime database, otherwise you'll be charged for every read/write operation as explained in my answer from this post. So using Firebase Realtime database you can host the number of likes at no cost.

So, how can be done? First of all, you are guessing right. The number of likes should be added beneath the postId like this:

Firebase-root
   |
   --- likes
         |
         --- postIdOne: numberOfLikes //must be stored as an integer
         |
         --- postIdOTwo: numberOfLikes //must be stored as an integer
         |
         --- //and so on

To achive what you want, you need to follow the next steps.

  1. Every time you you add a new post, add the corresponding post id in Firebase Realtime database like above by setting the value of that particular post id to 0.
  2. Every time you get a new like increase the value of that postId by one. Every time a user retracts a like, decrease the value of that postId by one. To achieve this and also to have consistent data, I recommend you use Firebase Transactions.
  3. Then in your adapter class, where you are displaying data from Firestore, when you want to set the number of likes to a view, just attach a listener on that particular post id node and get the number of likes. Inside the onDataChange() set that number to a TextView like this:

    DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
    DatabaseReference noOfLikesRef = rootRef.child("likes").child(postId);
    ValueEventListener valueEventListener = new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            String numberOfLikes = "(" + dataSnapshot.getValue() + ")";
            numberOfLikesTextView.setText(numberOfLikes);
        }
    
        @Override
        public void onCancelled(DatabaseError databaseError) {}
    };
    noOfLikesRef.addListenerForSingleValueEvent(valueEventListener);
    

That's it!



来源:https://stackoverflow.com/questions/49561360/using-data-from-firestore-and-firebase-rtdb-in-single-recyclerview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!