【问题标题】:Android Firebase listener inside onBindViewHolder of recyclerviewrecyclerview的onBindViewHolder内的Android Firebase监听器
【发布时间】:2017-03-28 03:59:46
【问题描述】:

我有一个 Android 聊天应用程序,它将所有消息都存储在本地 SQLite 数据库和 Firebase 实时数据库中。

在 RecyclerView 中显示消息时,我从本地数据库中查询它们(因为本地存储了一些额外的数据,而不是存储在实时数据库中)。

我需要实时更新显示的消息发送和读取状态,这是我从实时数据库获得的。

在recycler view的onBindViewHolder里面给每条消息设置一个value事件监听器会不会好?

这样我只听当前显示在屏幕上的消息的变化,而不是从服务器获取整个消息列表。(正是我需要的)

2 个问题: - 这个解决方案很好还是有更好的方法? - 我需要删除在回收站视图中已经不可见的项目的侦听器。我该怎么做?

我不使用 FirebaseUI(我知道它可以解决我的问题),但我想从我的本地数据库而不是服务器中显示数据,并且只从 firebase 实时获取一个字段的更新数据库。

【问题讨论】:

    标签: firebase android-recyclerview firebase-realtime-database firebaseui


    【解决方案1】:

    这个解决方案好还是有更好的方法?

    是的,不是的!我会建议你使用 FirebaseUI,这绝对是最好的选择,但你已经提到你不想使用它。因此,考虑到不使用 FirebaseUI 的事实,这似乎是最好的选择。 [我建议您直接从能够为您提供准确答案的 Firebase 人员那里获取有关此问题的评论。]您还应该知道,如果您在视图离开屏幕后不删除回调,你最终会得到成百上千的听众,(其中大多数是多余的)悬而未决并吃掉记忆,实际上什么都不做。

    我需要删除在回收站视图中已经不可见的项目的侦听器。我该怎么做?

    很简单。您可以使用recyclerViewonViewDetachedFromWindow(MyViewHolder holder) 方法,它为您提供即将从视图中删除的处理程序。您可以使用此调用来删除回调。

    怎么做?

    followRef.removeEventListener(followListener);
    

    问题是 - 您需要回调的引用才能将其从该位置移除。您可以通过两种方式做到这一点。如果您有太多不同的听众,您可以创建一个hashmap 来跟踪您的所有听众。每当需要时,您可以获取侦听器的引用并将其删除。

    另一种方式是:

    @Override
    public void onBindViewHolder(final MyViewHolder holder, int position) {
        User user = data.get(position);
        holder.name.setText(user.Name);
        holder.surname.setText(user.Surname);
        holder.id = user.id; //Id is same as the key used to point this user.
        holder.followers.setText("Loading..");
        DatabaseReference userFollowers = mRef.child(holder.id).child("Followers");
        followListener = new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                holder.followers.setText(String.valueOf(dataSnapshot.getValue()));
            }
    
            @Override
            public void onCancelled(DatabaseError databaseError) {
    
            }
        };
        userFollowers.addValueEventListener(followListener); //Adds a listener
    }
    
    @Override
    public void onViewDetachedFromWindow(MyViewHolder holder) {
        DatabaseReference followRef = mRef.child(holder.id).child("Followers");
        followRef.removeEventListener(followListener); //Removes the listener
        super.onViewDetachedFromWindow(holder);
    }
    

    代码可能有小错误,我是按照这个问题写的。没有测试。但我希望你明白了。

    问题:[即使这件事有一个小问题,我仍在努力寻找谁是最好的解决方案]:当您关闭包含 recyclerView 的活动时,函数 onViewDetachedFromWindow(MyViewHolder holder) 不会被调用特定时间屏幕上的项目。因此,每当recyclerView 活动结束时,它都会保留一些未删除的回调(与屏幕上可见项目的数量相同)。

    即使我最近也深入研究了 Firebase 数据库。欢迎对答案提出任何改进/建议。

    【讨论】:

      【解决方案2】:

      在 Cloud Firestore 中,您无需将内容保存在 SQLite 中,因为 Firestore 已经处理了缓存,以防监听器可能使用类似的东西。

      private ListenerRegistration registration;
      

      然后在你的 onBindView 中你可以这样做。

      registration = query.addSnapshotListener(new EventListener<QuerySnapshot>() {
          @Override
          public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {
          });
      

      在 onDetach 中

      if(registration != null)
      registration.remove();
      

      根据this 文档,它代表一个侦听器,因此使用 addSnapShotListener 对其进行初始化是正确的做法。另外我认为将监听器放在 ViewHolder 中是非常合适的,这样当事情被回收时,你可以使用它并在 onViewAttachedFromWindow 和 onViewDetachedFromWindow 中操作它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-03
        • 2016-11-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多