首页 > 解决方案 > 监听依赖于 Firebase 中另一个值的更改值

问题描述

我有一个名为RecentChats 的节点和另一个名为Users 的节点。在我的代码中,我首先获取了最近聊天,然后,对于每个最近聊天,我从 Firebase 获取远程用户。如下图所示,每个用户都有一个名为 lastSeen 的孩子。我希望能够听那个孩子的声音,并根据它的价值从布局中改变视图。在当前状态下,当其各自的最近聊天发生变化时,将再次检索用户值。我无法使 User 侦听器独立于 RecentChat 侦听器。

这是用户数据结构:

这是来自 RecyclerView 的项目(正如我所说,我希望能够根据用户状态实时更改点的颜色): 在此处输入图像描述

最近聊天片段.java

public class RecentChatsFragment extends Fragment {

    private final DatabaseReference recentChatsRef = FirebaseDatabase.getInstance()
                .getReference(KEY_COLLECTION_RECENT_CHATS);
    private ValueEventListener incomingMessagesListener;

    private List<RecentChat> recentChatList;
    private List<User> remoteUserList;

    private RecyclerView recentChatsRV;
    private TextView errorMessageTV;
    private CardView welcomingCV;
    private ProgressBar recentChatsPB;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_recent_chats, container, false);

        errorMessageTV = view.findViewById(R.id.errorMessageTV);
        welcomingCV = view.findViewById(R.id.welcomingCV);

        setupRV(view);
        setupFab(view);
        getRecentChats();
        return view;
    }

    private void setupRV(View view) {
        recentChatList = new ArrayList<>();
        remoteUserList = new ArrayList<>();
        recentChatsPB = view.findViewById(R.id.recentChatsPB);
        recentChatsRV = view.findViewById(R.id.recentChatsRV);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
        linearLayoutManager.setReverseLayout(true);
        linearLayoutManager.setStackFromEnd(true);
        recentChatsRV.setLayoutManager(linearLayoutManager);
    }

    private void setupFab(View view) {
        view.findViewById(R.id.usersListFB).setOnClickListener(v -> {
            Intent intent = new Intent(getContext(), UsersListChatsActivity.class);
            startActivity(intent);
        });
    }

    private void getRecentChats() {
        changeViewsVisibility(View.GONE, View.GONE, View.GONE, View.VISIBLE);
        incomingMessagesListener = recentChatsRef.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                if (snapshot.getValue() != null) {
                    final int[] i = {0};
                    recentChatList.clear();
                    for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
                        String[] usersID = dataSnapshot.getKey().split("-");
                        if (FIREBASE_USER.getUid().equals(usersID[0]) || FIREBASE_USER.getUid().equals(usersID[1])) {
                            RecentChat recentChat = dataSnapshot.getValue(RecentChat.class);
                            if (FIREBASE_USER.getUid().equals(usersID[0])) {
                                recentChat.setRemoteUserID(usersID[1]);
                            } else {
                                recentChat.setRemoteUserID(usersID[0]);
                            }
                            recentChatList.add(recentChat);
                        }
                        if (++i[0] == snapshot.getChildrenCount()) {
                            checkChatList();
                        }
                    }
                } else {
                    changeViewsVisibility(View.GONE, View.GONE, View.VISIBLE, View.GONE);
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError error) {
                errorMessageTV.setText(String.format("%s", getString(R.string.no_users_available)));
                changeViewsVisibility(View.GONE, View.VISIBLE, View.GONE, View.GONE);
            }
        });
    }

    private void getRemoteUser() {
        remoteUserList.clear();
        for (RecentChat recentChat : recentChatList) {
            FirebaseDatabase.getInstance().getReference(KEY_COLLECTION_USERS)
                    .child(recentChat.getRemoteUserID())
                    .addListenerForSingleValueEvent(new ValueEventListener() {
                        @Override
                        public void onDataChange(@NonNull DataSnapshot snapshot) {
                            User remoteUser = snapshot.getValue(User.class);
                            remoteUser.setId(snapshot.getKey());
                            remoteUserList.add(remoteUser);
                            if (remoteUserList.size() == recentChatList.size()) {
                                recentChatsRV.setAdapter(new RecentChatsAdapter(
                                        getContext(),
                                        recentChatList,
                                        remoteUserList)
                                );
                                changeViewsVisibility(View.VISIBLE, View.GONE, View.GONE, View.GONE);
                            }
                        }

                        @Override
                        public void onCancelled(@NonNull DatabaseError error) {
                            errorMessageTV.setText(String.format("%s", getString(R.string.no_users_available)));
                            changeViewsVisibility(View.GONE, View.VISIBLE, View.GONE, View.GONE);
                        }
                    });
        }
    }

    private void checkChatList() {
        if (recentChatList.size() > 0) {
            sortListAlphab(); //Ordering by timestamp
            getRemoteUser();
        } else {
            changeViewsVisibility(View.GONE, View.GONE, View.VISIBLE, View.GONE);
        }
    }

    private void sortListAlphab() {
        Collections.sort(recentChatList, (recentChatList, rc1) -> {
            long s1 = recentChatList.getTimestamp();
            long s2 = rc1.getTimestamp();
            return Long.compare(s1, s2);
        });
    }

    private void changeViewsVisibility(int recentChatsVis, int errorMessageVis, int welcomingVis, int pbVis) {
        recentChatsRV.setVisibility(recentChatsVis);
        errorMessageTV.setVisibility(errorMessageVis);
        welcomingCV.setVisibility(welcomingVis);
        recentChatsPB.setVisibility(pbVis);
    }

    @Override
    public void onPause() {
        super.onPause();
        if (incomingMessagesListener != null) {
            recentChatsRef.removeEventListener(incomingMessagesListener);
        }
    }
}

编辑: 问题是我从 Firebase 检索数据的方式。这就是让从 User 节点监听更改有点困难的原因。理想的做法是让RecentChats 和Users 值彼此独立,以便能够单独收听他们的更改,由于RecentChats 对Users 的依赖性,我认为这种方法是不可能的。我尝试在 getRemoteUser() 上将 addSingleValueEventListener 更改为 addValueEventListener,但没有成功。我正在寻找一种解决方法,我仍然可以在其中收听最近的聊天更改以及用户更改。

标签: androidfirebasefirebase-realtime-database

解决方案


推荐阅读