在Recyclerview的onBindViewHolder里面安装Android Firebase监听器

时间:2016-11-14 13:36:35

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

我有一个Android聊天应用,它可以存储本地SQLite数据库和Firebase实时数据库中的所有消息。

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

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

为回收站视图的onBindViewHolder中的每条消息设置值事件侦听器是否可以?

这样我只会收听当前显示在屏幕上的消息中的更改,并且不会从服务器获取整个消息列表。(正是我需要的)

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

我没有使用FirebaseUI(我意识到它解决了我的问题),但我想从我的本地数据库而不是从服务器提供数据,只在一个字段上获取更新来自firebase实时数据库。

2 个答案:

答案 0 :(得分:2)

  

此解决方案是否正常或有更好的方法?

是的,不!我会建议你FirebaseUI绝对是最好的选择,但你已经提到过你不想使用它。因此,不使用FirebaseUI的事实,这似乎是最好的选择。 [我建议您直接从可以为您提供准确答案的Firebase人员对此进行评论。] 您还应该知道,一旦视图离开屏幕,您就不会删除回调,你最终将会有成千上万的听众(他们中的大多数都是多余的)晃来晃去,吃掉了记忆,什么都不做。

  

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

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

如何?

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的活动时,函数{{ 1}}在特定时间没有为屏幕上的项目调用。因此,只要onViewDetachedFromWindow(MyViewHolder holder)活动结束,它就会保留很少的回调(与屏幕上可见项目的数量相同)。

即使我最近潜入Firebase数据库。欢迎任何改进/建议。

答案 1 :(得分:0)

在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中使用它并对其进行操作。