如果 Firebase 实时数据库中包含列表,我如何检索对象?

Posted

技术标签:

【中文标题】如果 Firebase 实时数据库中包含列表,我如何检索对象?【英文标题】:How can I retrieve an object from the Firebase RealTime Database if it contains a List? 【发布时间】:2021-12-09 23:10:00 【问题描述】:

我正在尝试学习如何使用 Firebase,并决定制作一个使用 Firebase 实时数据库的简单 android 应用程序。游戏需要一个主持大厅的主持人,以及可以加入该大厅的玩家。我做了一个主机类,它有一堆数据类型,其中有一个列表(游戏涉及使用主机给玩家的提示)。当我尝试从数据库中读取数据时遇到了问题。

我的大厅是一个列表视图,我想用数据库中的主机列表填充它,但是当我尝试从中读取时,我收到了这个讨厌的错误:

com.google.firebase.database.DatabaseException:类 java.util.List 具有泛型类型参数,请改用 GenericTypeIndicator

我知道还有其他关于同一错误的问题,但我无法成功应用这些答案。我是 android 开发的新手,非常感谢任何帮助。

这是我的用户定义类:

public class HostPlayer 

    private String hostName;
    private String photoUrl;
    private String primaryHint;
    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;

    public void setHints(List 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;

    public List getHints() return this.hints;

    public void setInProgress() this.inProgress = true;

    public boolean getInProgress() return this.inProgress;

这是我从数据库中读取的代码:

public class JoinGame extends AppCompatActivity 

    ListView lv;

    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) 
                HostPlayer hostPlayer = snapshot.getValue(HostPlayer.class); //this is where the error happens
                hostPlayerList.add(hostPlayer);
            

            @Override
            public void onCancelled(@NonNull DatabaseError error) 

            
        ;
        pDatabaseReference.addChildEventListener(pChildEventListener);

        lv = findViewById(R.id.listView_hosts);

        ArrayAdapter<HostPlayer> hostPlayerArrayAdapter = new ArrayAdapter<HostPlayer>(
                this, android.R.layout.simple_list_item_1, hostPlayerList
        );//making an arrayAdapter out of the list of HostPlayer objects

        lv.setAdapter(hostPlayerArrayAdapter);
    

数据库 JSON 的结构如下:


  "hosts" : 
    "some-data-key" : 
      "hints" : [ "first hint", "second hint" ],
      "hostName" : "mom",
      "inProgress" : false,
      "numHints" : 3,
      "numTime" : 30,
      "primaryHint" : "Living Room"
    
  ,
  "players" : 
    "another-data-key" : 
      "hostName" : "firstName",
      "inProgress" : false,
      "numHints" : 0,
      "numTime" : 0
    
  

我知道“提示”列表导致了这个错误,但仍然不明白为什么以及如何解决它。我将不胜感激任何解释和/或解决方案。感谢您的时间和帮助。

编辑:我忘记粘贴 logcat,这里是:

2021-10-23 16:11:20.732 21137-21137/com.example.treasurehunt E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.treasurehunt, PID: 21137
    com.google.firebase.database.DatabaseException: Class java.util.List has generic type parameters, please use GenericTypeIndicator instead
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToClass(CustomClassMapper.java:224)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToType(CustomClassMapper.java:179)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.access$100(CustomClassMapper.java:48)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper$BeanMapper.deserialize(CustomClassMapper.java:593)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper$BeanMapper.deserialize(CustomClassMapper.java:563)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertBean(CustomClassMapper.java:433)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToClass(CustomClassMapper.java:232)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertToCustomClass(CustomClassMapper.java:80)
        at com.google.firebase.database.DataSnapshot.getValue(DataSnapshot.java:203)
        at com.example.treasurehunt.JoinGame$1.onChildAdded(JoinGame.java:41)
        at com.google.firebase.database.core.ChildEventRegistration.fireEvent(ChildEventRegistration.java:79)
        at com.google.firebase.database.core.view.DataEvent.fire(DataEvent.java:63)
        at com.google.firebase.database.core.view.EventRaiser$1.run(EventRaiser.java:55)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

【问题讨论】:

你能粘贴你的崩溃日志吗? 抱歉,我刚刚粘贴了错误。谢谢! ***.com/questions/30744224/…?或来自***.com/… 的其他最佳答案之一。 您是否尝试过 Frank van Puffelen 评论中的解决方案?有用吗? 感谢您的帮助,感谢 Frank Van Puffelen。虽然我没有得到想要的输出(我的列表视图是空的,即使它不应该是),但我不再收到错误,所以我认为问题已得到解决。感谢您的支持! 【参考方案1】:

我改编了 Frank 和 Alex 在他们的 cmets 中提到的答案。它似乎在你的情况下工作。而不是直接使用 snapshot.getValue(HostPlayer.class); 使用这样的 GenericTypeIndicator;

    pChildEventListener = new ChildEventListener() 
        @Override
        public void onChildAdded(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) 
            GenericTypeIndicator<HostPlayer> t = new GenericTypeIndicator<HostPlayer>() ;
            HostPlayer hostPlayer = snapshot.getValue(t);//I was able to get the list without an error
            ...
        
        ...
    ;

【讨论】:

以上是关于如果 Firebase 实时数据库中包含列表,我如何检索对象?的主要内容,如果未能解决你的问题,请参考以下文章

将Firebase字段数组转换为列表

如何在我的 firebase 和 flutter 应用上创建实时用户数?

如何绘制列表中包含列表的数据表?

在 React App 中包含 firebase 时出现 TypeError

将 Firebase 实时数据库与 SwiftUI 列表一起使用 - 清除列表

EXC_BAD_ACCESS 代码=2 在 Podfile 中包含 Firebase/Auth