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

如何读取Firebase Realtime Database中包含List的自定义对象?

错误原因

Firebase Realtime Database 反序列化自定义类时,要求类的字段、get/set 方法完全符合 JavaBean 规范,且泛型声明完整。你遇到的报错核心原因是 HostPlayer 类中 hints 字段对应的 get、set 方法没有明确指定泛型为 String,Java 泛型擦除机制导致 Firebase 无法识别 List 内存储的数据类型,因此抛出需要使用 GenericTypeIndicator 的异常。

解决方案

方案1:修复 HostPlayer 的泛型声明(优先尝试)

修改 HostPlayer 类的字段访问权限、get/set 方法的泛型声明,符合 Firebase 反序列化要求,修改后的完整类代码如下:

public class HostPlayer {

    private String hostName;
    private String photoUrl;
    private String primaryHint;
    private List<String> hints = new ArrayList<String>();
    private int numHints;
    private int numTime;
    private boolean inProgress = false;

    public HostPlayer() {

    }

    public HostPlayer(String hostName, int numHints, int numTime, List<String> hints, String primaryHint, String photoUrl) {
        this.hostName = hostName;
        this.numHints = numHints;
        this.numTime = numTime;
        this.hints = hints;
        this.primaryHint = primaryHint;
        this.photoUrl = photoUrl;
        this.inProgress = false;
    }

    public void setPhotoUrl(String photoUrl) {this.photoUrl = photoUrl;}

    public void setPrimaryHint(String primaryHint) {this.primaryHint = primaryHint;}

    // 修正setHints的泛型声明
    public void setHints(List<String> hints) {this.hints = hints;}

    public String getHostName() {return this.hostName;}

    public int getNumHints() {return this.numHints;}

    public  int getNumTime() {return this.numTime;}

    public String getPrimaryHint() {return this.primaryHint;}

    // 修正getHints的泛型声明
    public List<String> getHints() {return this.hints;}

    public void setInProgress() {this.inProgress = true;}

    public boolean getInProgress() {return this.inProgress;}
}

修改完成后直接运行测试,绝大多数场景下改完泛型声明就可以解决报错。

方案2:手动解析数据(方案1无效时使用)

如果方案1修改后仍然报错,可以放弃自动反序列化,手动读取 DataSnapshot 的字段构造 HostPlayer 对象,步骤如下:

  1. 把 JoinGame 类中的适配器改为成员变量,方便后续刷新列表
  2. 在 onChildAdded 方法中手动读取各字段,用 GenericTypeIndicator 读取 hints 列表
  3. 新增数据后调用 notifyDataSetChanged 刷新 ListView

修改后的 JoinGame 完整代码如下:

public class JoinGame extends AppCompatActivity {

    ListView lv;
    ArrayAdapter<HostPlayer> hostPlayerArrayAdapter; // 适配器改为成员变量

    private FirebaseDatabase pFireBaseDatabase;
    private DatabaseReference pDatabaseReference;
    private ChildEventListener pChildEventListener;

    List<HostPlayer> hostPlayerList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_join_game);

        pFireBaseDatabase = FirebaseDatabase.getInstance();
        pDatabaseReference = pFireBaseDatabase.getReference().child("hosts");

        pChildEventListener = new ChildEventListener() {
            @Override
            public void onChildAdded(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
                // 手动读取各基础字段
                String hostName = snapshot.child("hostName").getValue(String.class);
                int numHints = snapshot.child("numHints").getValue(Integer.class) != null ? snapshot.child("numHints").getValue(Integer.class) : 0;
                int numTime = snapshot.child("numTime").getValue(Integer.class) != null ? snapshot.child("numTime").getValue(Integer.class) : 0;
                String primaryHint = snapshot.child("primaryHint").getValue(String.class);
                String photoUrl = snapshot.child("photoUrl").getValue(String.class);
                boolean inProgress = snapshot.child("inProgress").getValue(Boolean.class) != null && snapshot.child("inProgress").getValue(Boolean.class);

                // 用GenericTypeIndicator读取泛型List
                GenericTypeIndicator<List<String>> hintsType = new GenericTypeIndicator<List<String>>() {};
                List<String> hints = snapshot.child("hints").getValue(hintsType);

                // 构造HostPlayer对象
                HostPlayer hostPlayer = new HostPlayer(hostName, numHints, numTime, hints, primaryHint, photoUrl);
                if (inProgress) {
                    hostPlayer.setInProgress();
                }
                hostPlayerList.add(hostPlayer);
                // 刷新列表
                hostPlayerArrayAdapter.notifyDataSetChanged();
            }

            @Override
            public void onCancelled(@NonNull DatabaseError error) {

            }
        };
        pDatabaseReference.addChildEventListener(pChildEventListener);

        lv = findViewById(R.id.listView_hosts);

        hostPlayerArrayAdapter = new ArrayAdapter<HostPlayer>(
                this, android.R.layout.simple_list_item_1, hostPlayerList
        );

        lv.setAdapter(hostPlayerArrayAdapter);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 13:54:04