如何根据Firebase唯一Key在RecyclerView中匹配展示指定账单数据?
解决FirebaseRecyclerAdapter添加
.child(keyValue)后崩溃的问题 首先咱们来拆解崩溃的核心原因:
你原本的mRef = FirebaseDatabase.getInstance().getReference().child("Bills")指向的是一个包含多个账单节点的集合,FirebaseRecyclerAdapter就是为处理这类列表数据设计的,所以能正常展示所有账单。
但当你加上.child(keyValue)后,mRef就指向了单个账单的具体节点(比如截图里的-N...xxx层级),此时这个节点是单一的DataModel对象,而非列表集合。FirebaseRecyclerAdapter只能解析列表类型的数据源,无法处理单个对象,因此直接触发崩溃。
另外要提前做校验:如果Intent传递的key为空,.child(keyValue)会变成.child(null),同样会导致崩溃,所以第一步必须先判断keyValue的有效性。
下面给你两种解决方案,可根据需求选择:
方案一:直接展示单个账单(无需RecyclerView)
如果只需要展示匹配key的这一个账单,完全没必要用RecyclerView,直接读取单个节点数据绑定到布局控件即可:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_data_save); Intent intent = getIntent(); if(intent == null || intent.getStringExtra("key") == null) { // 处理key为空的异常情况 Toast.makeText(this, "无效的账单Key", Toast.LENGTH_SHORT).show(); finish(); return; } keyValue = intent.getStringExtra("key"); // 获取单个账单的数据库引用 DatabaseReference singleBillRef = FirebaseDatabase.getInstance().getReference() .child("Bills").child(keyValue); // 读取单个账单数据 singleBillRef.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { if(snapshot.exists()) { DataModel model = snapshot.getValue(DataModel.class); // 直接绑定布局中的TextView TextView billNoTv = findViewById(R.id.receiptBillNo); TextView storeNameTv = findViewById(R.id.receiptStoreName); TextView dateTv = findViewById(R.id.receiptDate); TextView timeTv = findViewById(R.id.receiptTime); TextView totalTv = findViewById(R.id.receiptTotal); billNoTv.setText("Bill No : " + model.getBillNo()); storeNameTv.setText("Store Name : " + model.getCompany()); dateTv.setText("Date : " + model.getDate()); timeTv.setText("Time : " + model.getTime()); totalTv.setText("Total : " + model.getTotal()); } else { Toast.makeText(DataSaveActivity.this, "未找到对应账单", Toast.LENGTH_SHORT).show(); } } @Override public void onCancelled(@NonNull DatabaseError error) { Toast.makeText(DataSaveActivity.this, "读取数据失败:" + error.getMessage(), Toast.LENGTH_SHORT).show(); } }); }
方案二:用RecyclerView展示单个匹配项(保留列表结构)
如果一定要保留RecyclerView(比如后续可能扩展展示多个匹配账单),可以用orderByKey().equalTo(keyValue)构建查询,这样返回的是包含单个元素的列表,FirebaseRecyclerAdapter就能正常处理:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_data_save); mReceipt = findViewById(R.id.othersRecycler); mReceipt.setLayoutManager(new LinearLayoutManager(this)); Intent intent = getIntent(); if(intent == null || intent.getStringExtra("key") == null) { Toast.makeText(this, "无效的账单Key", Toast.LENGTH_SHORT).show(); finish(); return; } keyValue = intent.getStringExtra("key"); // 构建查询:筛选出key与keyValue匹配的账单 Query billQuery = FirebaseDatabase.getInstance().getReference() .child("Bills") .orderByKey() .equalTo(keyValue); // 使用Query作为数据源初始化适配器 FirebaseRecyclerAdapter<DataModel, ReceiptViewHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<DataModel, ReceiptViewHolder> (DataModel.class, R.layout.reciept_row, ReceiptViewHolder.class, billQuery){ @Override protected void populateViewHolder(ReceiptViewHolder viewHolder,DataModel model, int position) { viewHolder.setBillNo("Bill No : " + model.getBillNo()); viewHolder.setStoreName("Store Name : " + model.getCompany()); viewHolder.setDate("Date : " + model.getDate()); viewHolder.setTime("Time : " + model.getTime()); viewHolder.setBillTotal("Total : " + model.getTotal()); } }; mReceipt.setAdapter(firebaseRecyclerAdapter); }
额外注意:请确保你的DataModel类字段与Firebase节点中的字段完全对应(包括大小写),否则会出现数据解析失败的问题。
内容的提问来源于stack exchange,提问作者mav-raj
相关产品推荐
相关产品推荐

