【问题标题】:Using data from Firestore and Firebase RTDB in single RecyclerView在单个 RecyclerView 中使用来自 Firestore 和 Firebase RTDB 的数据
【发布时间】:2018-09-08 17:22:24
【问题描述】:

我有一个 RecyclerView,它由存储在 Firestore 数据库中的帖子填充。 每个帖子都写成一个具有唯一 postID 的文档,存储发布的消息、时间戳和点赞计数器。

    //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 {
                        //...
                    }
                }
            });

在尝试为这些帖子实现“点赞”功能时,我遇到了 Firestore 的限制,它每秒只能处理一个文档更新。

阅读this article 说服我使用 Firebase 实时数据库通过使用事务操作而不是使用 distributed counters 来存储喜欢。我不想实时显示喜欢,我只想使用 RTDB 来处理每秒多个喜欢/不喜欢。

当另外使用 Firebase RTDB 进行点赞时,我会将数据添加到路径 /posts/postID/likes。

如何从 Firestore 获取帖子消息并将 RTDB 中的相应点赞添加到mUploads,然后再将其传递给适配器。具体来说,是否可以确保我为其对应的帖子设置了正确的类似值,而无需查询每个 postID。

【问题讨论】:

    标签: android firebase android-recyclerview google-cloud-firestore


    【解决方案1】:

    对于 Firestore,这是一种非常常见的做法,将喜欢的数量存储在 Firebase 实时数据库中,否则您将按我在post 的回答中解释的每次读/写操作付费。因此,使用 Firebase 实时数据库,您可以免费托管喜欢的数量。

    那么,怎么做呢?首先,你猜对了。喜欢的数量应该添加在postId 下方,如下所示:

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

    要实现您想要的,您需要执行以下步骤。

    1. 每次添加新帖子时,通过将特定帖子 ID 的值设置为 0,在 Firebase 实时数据库中添加相应的帖子 ID,如上所示。
    2. 每次收到新的赞时,都会将该 postId 的值加一。每次用户撤回点赞时,将该 postId 的值减一。为了实现这一点并获得一致的数据,我建议您使用Firebase Transactions
    3. 然后,在您显示来自 Firestore 的数据的适配器类中,当您想要设置视图的点赞数时,只需在该特定帖子 ID 节点上附加一个侦听器并获取点赞数。在onDataChange() 中将该数字设置为TextView,如下所示:

      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);
      

    就是这样!

    【讨论】:

    • 非常感谢@Alex Mamo!我接受了这个作为答案,因为它解决了上述问题。但是,我对此声明有一个评论和一个问题:“使用 Firebase 实时数据库,您可以免费托管喜欢的数量。”在适配器中使用 onDataChange() 时(更具体地说,在 onBindViewHolder 中)我在 Firebase 中生成了大量下载。由于我只加载微小的有效负载,这似乎是由于巨大的开销(通过高频率读取?),这似乎提高了 Firebase 的下载统计数据和奖品。我误解了您的回答还是有解决方法:)?
    • 当我说免费时,这意味着您不会为您获得的每一个赞收费。在 Cloud Firestore 中,对于 100 个赞,您需要为 100 次写入操作付费。在 Firebase 实时数据库中,没有这样的计划。如您所见,我使用了addListenerForSingleValueEvent,它只会下载一次数据。
    • 我明白了。虽然它是单值事件的监听器,但在我的案例中使用非常频繁。总是当一个视图被绑定时(这对我来说经常发生),一个对数据库的请求就完成了。滚动浏览我的卡片时,我收到了一个非常频繁的阅读请求。我不太了解开销以及我的假设是否正确,我所能看到的是,当分别存储“仅”10 个帖子和 10 个类似值时,正常操作每小时只有 1 个用户获得约 2 MB 的下载量.
    • 是的,对数据库的请求已完成。这是因为您正在读取每个视图的点赞数但是请记住,您不需要在 onBindViewHolder 方法中执行此操作,您需要在您的 holder 类中执行此操作,您正在将数据设置为对应TextView,否则滚动时,每次都会触发onBindViewHolder
    • 字!我应该把它放在我的 onBindViewHolder 之外。谢谢,我会这样做并提供有关使用数字的更新以进行澄清!
    猜你喜欢
    • 1970-01-01
    • 2021-11-09
    • 2016-07-19
    • 1970-01-01
    • 2020-09-06
    • 1970-01-01
    • 1970-01-01
    • 2020-09-17
    • 2018-08-22
    相关资源
    最近更新 更多