recyclerview的onBindViewHolder内的Android Firebase监听器
Posted
技术标签:
【中文标题】recyclerview的onBindViewHolder内的Android Firebase监听器【英文标题】:Android Firebase listener inside onBindViewHolder of recyclerview 【发布时间】:2017-03-28 03:59:46 【问题描述】:我有一个 android 聊天应用程序,它将所有消息都存储在本地 SQLite 数据库和 Firebase 实时数据库中。
在 RecyclerView 中显示消息时,我从本地数据库中查询它们(因为本地存储了一些额外的数据,而不是存储在实时数据库中)。
我需要实时更新显示的消息发送和读取状态,这是我从实时数据库获得的。
在recycler view的onBindViewHolder里面给每条消息设置一个value事件监听器会不会好?
这样我只听当前显示在屏幕上的消息的变化,而不是从服务器获取整个消息列表。(正是我需要的)
2 个问题: - 这个解决方案很好还是有更好的方法? - 我需要删除在回收站视图中已经不可见的项目的侦听器。我该怎么做?
我不使用 FirebaseUI(我知道它可以解决我的问题),但我想从我的本地数据库而不是服务器中显示数据,并且只从 firebase 实时获取一个字段的更新数据库。
【问题讨论】:
【参考方案1】:这个解决方案好还是有更好的方法?
是的,不是的!我会建议你使用 FirebaseUI,这绝对是最好的选择,但你已经提到你不想使用它。因此,考虑到不使用 FirebaseUI 的事实,这似乎是最好的选择。 [我建议您直接从能够为您提供准确答案的 Firebase 人员那里获取有关此问题的评论。]您还应该知道,如果您在视图离开屏幕后不删除回调,你最终会得到成百上千的听众,(其中大多数是多余的)悬而未决并吃掉记忆,实际上什么都不做。
我需要删除在回收站视图中已经不可见的项目的侦听器。我该怎么做?
很简单。您可以使用recyclerView
的onViewDetachedFromWindow(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 中操作它。
【讨论】:
以上是关于recyclerview的onBindViewHolder内的Android Firebase监听器的主要内容,如果未能解决你的问题,请参考以下文章