Firebase不同Reference间数据访问问题求助
解决Firebase跨监听器传递数据的问题
我来帮你搞定这个Firebase异步监听器之间的数据传递问题,先说说你之前嵌套监听崩溃的核心原因,再给你正确的实现方案:
崩溃原因分析
你之前的嵌套代码之所以崩溃,是因为混淆了两个不同Reference的DataSnapshot:外部监听器的dataSnapshot是来自databaseBazars(对应Bazar数据),但你在内部监听器里居然用同一个dataSnapshot去解析MealE对象,这会导致类型转换异常,直接触发崩溃。另外代码里重复多次获取MealE对象也是冗余且容易出错的操作。
正确的嵌套监听实现
嵌套监听本身是Firebase异步操作中传递数据的合理方式,只要我们区分开两个监听器的快照,确保数据来源正确就不会有问题。核心思路是:先在外部监听器中计算出mealrate,再启动内部监听器并直接使用这个已经计算好的值。
修正后的完整代码
databaseBazars.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot bazarSnapshot) { // 第一步:计算mealrate Integer mealrate = 0; for (DataSnapshot ds : bazarSnapshot.getChildren()) { Bazar bazar = ds.getValue(Bazar.class); Integer cost = Integer.valueOf(bazar.getCost()); mealrate += cost; } // 第二步:mealrate已就绪,启动第二个监听器处理Meal数据 DatabaseReference dbr = ...; // 确保这里是你正确的Meal数据引用 dbr.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot mealSnapshot) { abcd.clear(); Integer total = 0; Integer s1=0, s2=0, s3=0, s4=0, s5=0, s6=0, s7=0; for (DataSnapshot ds : mealSnapshot.getChildren()) { // 每个快照只解析一次MealE对象,避免冗余 MealE meal = ds.getValue(MealE.class); Integer costs1 = Integer.valueOf(meal.getS1()); Integer costs2 = Integer.valueOf(meal.getS2()); Integer costs3 = Integer.valueOf(meal.getS3()); Integer costs4 = Integer.valueOf(meal.getS4()); Integer costs5 = Integer.valueOf(meal.getS5()); Integer costs6 = Integer.valueOf(meal.getS6()); Integer costs7 = Integer.valueOf(meal.getS7()); // 累加各用户的餐数 s1 += costs1; s2 += costs2; s3 += costs3; s4 += costs4; s5 += costs5; s6 += costs6; s7 += costs7; // 计算总餐数+mealrate total += costs1 + costs2 + costs3 + costs4 + costs5 + costs6 + costs7 + mealrate; abcd.add(meal); } // 更新适配器和弹窗 MealList adapter = new MealList(ShowMeal.this, abcd); sm.setAdapter(adapter); AlertDialog.Builder dialog1 = new AlertDialog.Builder(ShowMeal.this); dialog1.setTitle("Notification"); dialog1.setMessage("Total Meal : " + total + "\n\n" + "Nayeem : " + s1 + "\n\n" + "Nizam : " + s2 + "\n\n" + "Rabbani : " + s3 + "\n\n" + "Saikat : " + s4 + "\n\n" + "Sagar : " + s5 + "\n\n" + "Nayan : " + s6 + "\n\n" + "Touqir : " + s7 + "\n\n\n" + "MEAL RATE : " + mealrate); dialog1.setIcon(R.drawable.ic_done_black_24dp); dialog1.setNeutralButton("OK", (dialog, id) -> dialog.dismiss()); dialog1.show(); } @Override public void onCancelled(DatabaseError databaseError) { // 别忘了添加错误日志,方便调试 Log.e("FirebaseError", "获取Meal数据失败", databaseError.toException()); } }); } @Override public void onCancelled(DatabaseError databaseError) { Log.e("FirebaseError", "获取Bazar数据失败", databaseError.toException()); } });
优化建议(可选)
如果觉得嵌套代码可读性差,可以把第二个监听器的逻辑抽成单独的方法,让代码更清晰:
// 单独的处理方法 private void processMealData(Integer mealrate) { DatabaseReference dbr = ...; dbr.addListenerForSingleValueEvent(new ValueEventListener() { // 这里的逻辑和上面内部监听器完全一致,直接使用mealrate参数即可 }); } // 在外部监听器中调用 @Override public void onDataChange(DataSnapshot bazarSnapshot) { Integer mealrate = 0; // 计算mealrate的逻辑... processMealData(mealrate); }
内容的提问来源于stack exchange,提问作者Mamun Nayeem
相关产品推荐
相关产品推荐

