Android Firebase listener内部的onBindViewHolder的recyclerview



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

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

我需要有显示的消息发送和读取状态的实时更新,这是我从实时DB得到的。

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

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

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

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

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

是和不是!我会建议你使用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数据库。欢迎对答案提出任何改进/建议。

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

根据本文档,它代表一个监听器,所以用addSnapShotListener初始化它是正确的方法。另外,我认为把监听器放在ViewHolder中是非常合适的,这样你就可以在onViewAttachedFromWindow和onViewDetachedFromWindow中使用它当东西被回收时

最新更新