You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FirebaseUI结合Firebase Database查询多用户仅显示最后一个求助

我来帮你解决这个FirebaseUI只显示最后一个用户的问题!咱们先搞清楚问题出在哪,再一步步修改代码。

问题根源分析

你当前的代码里,每次onChildAdded触发时都会新建一个FirebaseRecyclerAdapter,然后直接设置给RecyclerView。这就相当于每次有新的用户ID进来,就用新的adapter覆盖掉之前的,最后RecyclerView自然就只显示最后一次查询到的用户了。

解决方案思路

我们需要先把所有需要展示的用户ID收集起来(还要去重,避免重复显示同一个用户),然后基于这个ID集合做一次批量查询,再用FirebaseUI渲染所有结果。如果后续有用户ID新增/移除,再实时更新查询即可。

修改后的完整代码
public class UserMessageListFragment extends Fragment { 
    private ProgressDialog progressDialog; 
    private final String TAG = "UsersMessageList"; 
    private RecyclerView mResultList; 
    private ArrayList<String> arrayUsers = new ArrayList<>(); // 用来存所有需要展示的用户ID
    private FirebaseRecyclerAdapter<User, UsersViewHolder> firebaseRecyclerAdapter; // 把adapter设为成员变量,方便后续更新

    public static UserMessageListFragment newInstance() { 
        return new UserMessageListFragment(); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
        View view = inflater.inflate(R.layout.fragment_user_message_list, container, false); 
        mResultList = view.findViewById(R.id.message_list); 
        mResultList.setHasFixedSize(true); 
        mResultList.setLayoutManager(new LinearLayoutManager(mResultList.getContext())); 

        final DatabaseReference refMessages = FirebaseDatabase.getInstance().getReference(); 
        final DatabaseReference ref= FirebaseDatabase.getInstance().getReference().child("usuarios"); 

        refMessages.addChildEventListener(new ChildEventListener() { 
            @Override 
            public void onChildAdded(DataSnapshot dataSnapshot, String s) { 
                if(dataSnapshot.getKey().contains(UserDetails.username+ "_")) { 
                    String[] userChatWithId = dataSnapshot.getKey().split(UserDetails.username+"_"); 
                    String targetUserId = userChatWithId[1];
                    // 避免重复添加同一个用户ID
                    if(!arrayUsers.contains(targetUserId)){
                        arrayUsers.add(targetUserId);
                        updateFirebaseUiQuery(ref); // 更新查询并刷新列表
                    }
                } 
            } 

            @Override 
            public void onChildChanged(DataSnapshot dataSnapshot, String s) { 
                // 消息更新时同步检查用户ID
                if(dataSnapshot.getKey().contains(UserDetails.username+ "_")) { 
                    String[] userChatWithId = dataSnapshot.getKey().split(UserDetails.username+"_"); 
                    String targetUserId = userChatWithId[1];
                    if(!arrayUsers.contains(targetUserId)){
                        arrayUsers.add(targetUserId);
                        updateFirebaseUiQuery(ref);
                    }
                }
            } 

            @Override 
            public void onChildRemoved(DataSnapshot dataSnapshot) { 
                // 消息删除时,移除对应的用户ID(可以额外检查是否还有其他消息关联该用户,这里简化处理)
                if(dataSnapshot.getKey().contains(UserDetails.username+ "_")) { 
                    String[] userChatWithId = dataSnapshot.getKey().split(UserDetails.username+"_"); 
                    String targetUserId = userChatWithId[1];
                    arrayUsers.remove(targetUserId);
                    updateFirebaseUiQuery(ref);
                }
            } 

            @Override 
            public void onChildMoved(DataSnapshot dataSnapshot, String s) { } 

            @Override 
            public void onCancelled(DatabaseError databaseError) { 
                Log.e(TAG, "数据库查询失败", databaseError.toException());
            } 
        }); 

        return view; 
    } 

    private void updateFirebaseUiQuery(DatabaseReference userRef){
        if(arrayUsers.isEmpty()){
            // 没有用户时清空列表
            if(firebaseRecyclerAdapter != null){
                firebaseRecyclerAdapter.stopListening();
                mResultList.setAdapter(null);
            }
            return;
        }

        // 批量查询所有目标用户:使用Firebase的in操作符(注意最多支持10个ID)
        Query firebaseSearchQuery = userRef.orderByChild("username").in(arrayUsers);

        FirebaseRecyclerOptions<User> options = new FirebaseRecyclerOptions.Builder<User>()
                .setQuery(firebaseSearchQuery, User.class)
                .build();

        if(firebaseRecyclerAdapter == null){
            // 第一次初始化adapter
            bindAndBuildFirebaseUi(options);
        } else {
            // 已有adapter时,直接更新查询选项
            firebaseRecyclerAdapter.updateOptions(options);
        }
    }

    public void bindAndBuildFirebaseUi(FirebaseRecyclerOptions options) { 
        firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<User, UsersViewHolder>(options) { 
            @Override 
            public UsersViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
                View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.message_list_layout, parent, false); 
                return new UsersViewHolder(v); 
            } 

            @Override 
            protected void onBindViewHolder(final UsersViewHolder holder, int position, final User model) { 
                holder.bind(model); 
                holder.itemView.setOnClickListener(new View.OnClickListener() { 
                    @Override 
                    public void onClick(View v) { 
                        UserDetails.chatWithId = model.getUsername(); 
                        UserDetails.chatWith = model.getName(); 
                        startActivity(new Intent(getContext(), Chat.class)); 
                    } 
                }); 
            } 
        }; 

        firebaseRecyclerAdapter.startListening(); 
        mResultList.setAdapter(firebaseRecyclerAdapter); 
    } 

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        // 页面销毁时停止监听,防止内存泄漏
        if(firebaseRecyclerAdapter != null){
            firebaseRecyclerAdapter.stopListening();
        }
    }
}
额外注意事项
  • in操作符的限制:Firebase Realtime Database的in查询最多支持10个值,如果你的用户ID超过10个,需要把集合分成多个10元素的子集分别查询,或者考虑改用Cloud Firestore(支持最多30个in值)。
  • 去重逻辑:添加用户ID时检查是否已存在,避免重复查询和显示同一个用户。
  • 生命周期管理:在onDestroyView中停止adapter的监听,这是避免内存泄漏的关键步骤。

内容的提问来源于stack exchange,提问作者user6246272

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:21:03