如何单次读取Firebase数据,在列表展示Book与Feed_modell对象避免重复
我明白你现在的困扰——每次从Firebase读取一条数据,你都同时把它解析成Feed_modell和Book两个对象并添加到列表里,这就导致每条原始数据在列表里重复出现了两次。要解决这个问题,我们只需要读取一次Firebase数据,然后根据数据的实际类型选择对应的模型解析,而不是同时解析两个模型。
问题根源
你的代码里,每个DataSnapshot都会被同时转换成两个模型并加入列表,这就是重复数据的直接来源:
@Override public void onChildAdded(DataSnapshot dataSnapshot, String s) { Feed_modell post = dataSnapshot.getValue(Feed_modell.class); Book book = dataSnapshot.getValue(Book.class); feedList.add(post); feedList.add(book); // 同一条数据被添加了两次 Adapter.notifyDataSetChanged(); }
解决方案
方案1:根据数据标识区分解析(推荐)
如果你的feedPosts节点下同时存在Feed和Book两种类型的数据,可以给每条数据添加一个类型标识字段(比如itemType),然后根据这个字段判断该解析成哪个模型:
private RecyclerViewFeedAdapter Adapter; private List<Object> feedList; private void loadtheFeed() { // 初始化或清空列表 if (feedList == null) { feedList = new ArrayList<>(); } else { feedList.clear(); } DatabaseReference dbs = FirebaseDatabase.getInstance().getReference("feedPosts"); Query query = dbs.child(feedReceivingKey); childEventListener1 = query.addChildEventListener(new ChildEventListener() { @Override public void onChildAdded(DataSnapshot dataSnapshot, String s) { // 读取数据中的类型标识 String itemType = dataSnapshot.child("itemType").getValue(String.class); if (itemType != null) { switch (itemType) { case "feed": Feed_modell post = dataSnapshot.getValue(Feed_modell.class); feedList.add(post); break; case "book": Book book = dataSnapshot.getValue(Book.class); feedList.add(book); break; } // 用notifyItemInserted代替全量刷新,提升性能 Adapter.notifyItemInserted(feedList.size() - 1); } } @Override public void onChildChanged(DataSnapshot dataSnapshot, String s) {} @Override public void onChildRemoved(DataSnapshot dataSnapshot) {} @Override public void onChildMoved(DataSnapshot dataSnapshot, String s) {} @Override public void onCancelled(DatabaseError databaseError) {} }); } // 页面销毁时移除监听器,避免内存泄漏 @Override protected void onDestroy() { super.onDestroy(); if (childEventListener1 != null) { FirebaseDatabase.getInstance().getReference("feedPosts") .child(feedReceivingKey) .removeEventListener(childEventListener1); } }
方案2:只解析需要的模型
如果你的业务需求是每条数据只需要解析成其中一个模型(比如只需要Feed或者只需要Book),直接去掉其中一个解析和添加逻辑即可:
@Override public void onChildAdded(DataSnapshot dataSnapshot, String s) { // 只解析Feed_modell并添加 Feed_modell post = dataSnapshot.getValue(Feed_modell.class); feedList.add(post); Adapter.notifyItemInserted(feedList.size() - 1); // 或者只解析Book并添加 // Book book = dataSnapshot.getValue(Book.class); // feedList.add(book); // Adapter.notifyItemInserted(feedList.size() - 1); }
额外提示
- 你的
RecyclerViewFeedAdapter需要能处理Object类型的列表项,建议在适配器中用instanceof判断每个item的类型,加载对应的布局。 - 尽量使用
notifyItemInserted()代替notifyDataSetChanged(),前者只会刷新新增条目,性能更优。 - 务必在页面销毁时移除Firebase监听器,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Miguel Nuno
相关产品推荐
相关产品推荐

