android - 监听依赖于 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,但没有成功。我正在寻找一种解决方法,我仍然可以在其中收听最近的聊天更改以及用户更改。
解决方案
推荐阅读
- powershell - 将字符串转换为日期时间格式
- javascript - 在 Intranet 和 Internet 上在一页上设置不同的行为
- coinbase-api - 如何获取 Coinbase CryptoCurrency 硬币的列表
- python-2.7 - ValueError: 层权重形状 (32, 128) 与提供的权重形状 (32, 64) 不兼容
- gradle - gradle maven-publish 插件仅发布第一个子模块工件
- angular - Angular5 电子邮件自动完成/邮件检查器
- linux - 如何在无法启动的 Docker 容器中创建目录?
- dependency-injection - 关于依赖注入 - 如果来自较低级别类的方法签名被更改,是否必须更新注入的较高类?
- java - abc 后跟 def 后跟 ghi 以及单个单词的正则表达式
- php - 来自具有未知子深度和 char 类型列的邻接列表表的递归后代