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

Firebase嵌套ArrayList数据读取异常:无法完整获取日期字段及存值为null

解决Firebase数据读取与ListView展示的问题

嘿,我来帮你一步步搞定这些问题,让你的数据能正确读取并展示在ListView里:

问题根源分析与逐个解决

1. 无法读取datedata下的month和year字段

你的DateDataHelper类里有一个多余的带AccountBillList参数的构造函数,Firebase在反序列化数据时会优先匹配参数匹配的构造,这个空实现的构造会导致字段完全没被赋值。另外,Firebase要求实体类必须有无参构造函数,否则反序列化直接失败。

解决方案:

  • 删除那个带Activity参数的无用构造函数
  • 添加一个空实现的无参构造(Firebase反序列化必须)
  • 确保构造函数的参数名和Firebase节点里的字段名完全一致(你的代码里这点已经没问题)

2. 日期值存入ArrayList时显示为null

你声明的所有ArrayList(account、amount、date、month、year)都只是定义了变量,没有初始化实例!比如ArrayList<String> account;只是声明,没有new ArrayList<>(),调用add()时不仅会触发空指针,调试时自然显示为null。

解决方案:
初始化集合时一定要创建实例:

ArrayList<String> account = new ArrayList<>(); 
ArrayList<String> amount = new ArrayList<>(); 
ArrayList<String> date = new ArrayList<>();
ArrayList<String> month = new ArrayList<>();
ArrayList<String> year = new ArrayList<>();

3. 第二个for循环处理account和amount的逻辑问题

原来的逻辑里,外层循环每个purchasebill节点时先添加account和amount,再内层循环遍历datedata添加日期字段。但如果一个purchasebill有多个datedata,同一个account和amount会被对应到多个日期,而ListView需要的是每个条目对应一组完整日期+account+amount,分开存储多个ArrayList很容易导致数据错位。

更优解决方案:
创建一个专门的实体类封装ListView每个条目的数据,比如BillItem:

public class BillItem {
    private String fullDate;
    private String account;
    private String amount;

    // 无参构造,Firebase反序列化必须
    public BillItem() {}

    public BillItem(String fullDate, String account, String amount) {
        this.fullDate = fullDate;
        this.account = account;
        this.amount = amount;
    }

    // getter和setter方法
    public String getFullDate() { return fullDate; }
    public void setFullDate(String fullDate) { this.fullDate = fullDate; }
    public String getAccount() { return account; }
    public void setAccount(String account) { this.account = account; }
    public String getAmount() { return amount; }
    public void setAmount(String amount) { this.amount = amount; }
}

用ArrayList<BillItem>存储所有条目,数据对应关系绝对不会乱。

修正后的完整代码示例

1. 修正后的DateDataHelper类

class DateDataHelper { 
    private String date; 
    private String month; 
    private String year; 

    // 无参构造,Firebase反序列化必须
    public DateDataHelper() {}

    public DateDataHelper(String date, String month, String year) { 
        this.date = date; 
        this.month = month; 
        this.year = year; 
    } 

    // getter and setter方法
    public String getDate() { return date; }
    public void setDate(String date) { this.date = date; }
    public String getMonth() { return month; }
    public void setMonth(String month) { this.month = month; }
    public String getYear() { return year; }
    public void setYear(String year) { this.year = year; }
}

2. 修正后的Firebase数据读取逻辑

// 用封装好的BillItem集合存储数据
ArrayList<BillItem> billItemList = new ArrayList<>();
BillListAdapter billListAdapter = new BillListAdapter(AccountBillList.this, billItemList); // 适配你的Adapter

myRef = database.getReference("purchasebill"); 
myRef.addValueEventListener(new ValueEventListener() { 
    @Override 
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) { 
        // 每次数据变化先清空集合,避免重复添加
        billItemList.clear();
        
        for (DataSnapshot ds : dataSnapshot.getChildren()) { 
            BilllistHelper billlistHelper = ds.getValue(BilllistHelper.class); 
            if (billlistHelper == null) continue; // 空判断,避免空指针
            
            String account = billlistHelper.getAccount();
            String amount = billlistHelper.getAmount();

            // 遍历当前purchasebill下的所有datedata节点
            for (DataSnapshot dd : ds.child("datedata").getChildren()){ 
                DateDataHelper dateDataHelper = dd.getValue(DateDataHelper.class); 
                if (dateDataHelper == null) continue;
                
                // 拼接完整日期,格式可自行调整
                String fullDate = dateDataHelper.getDate() + "/" + dateDataHelper.getMonth() + "/" + dateDataHelper.getYear();
                
                // 创建BillItem并添加到集合
                billItemList.add(new BillItem(fullDate, account, amount));
            } 

            // 若需处理intendby和vendorname,可在BillItem中添加对应字段
            // intendby.add(billlistHelper.getIntendby()); 
            // vendorname.add(billlistHelper.getVendorName()); 
        } 
        billListAdapter.notifyDataSetChanged(); 
    } 

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {
        // 处理数据读取失败的情况
        Log.e("FirebaseError", "数据读取失败: " + databaseError.getMessage());
    }
});

3. 对应的Adapter修改(示例)

你的BillListAdapter需要适配BillItem类,在getView方法中获取对应字段:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    // 初始化View等逻辑...
    BillItem item = billItemList.get(position);
    tvFullDate.setText(item.getFullDate());
    tvAccount.setText(item.getAccount());
    tvAmount.setText(item.getAmount());
    return convertView;
}

这样修改后,三个问题就都解决了:Firebase能正确反序列化datedata的所有字段,集合不会再出现null,数据对应关系也不会错乱,ListView能正确展示每个条目的完整日期、account和amount。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:32:05