【问题标题】:Firebase Realtime Database retrieve last-child dataFirebase 实时数据库检索最后一个子数据
【发布时间】:2021-09-01 23:51:31
【问题描述】:

我正在尝试检索 Firebase 数据库中最后一个孩子的数据。

.

我想做的是添加另一个 Records 孩子,就像最后一个孩子的 id-number 一样,增加 1。 因此,在这种特定情况下,例如,我想创建一个名为“3”的子项,以及它的所有相关字段(id、月份、名称、时间)。

我尝试过使用下面的代码,但是当我运行它时,它永远不会进入 addListenerForSingleValueEvent(),我不知道为什么。它没有给我任何错误,但它根本没有进入方法。

String name = Joe;
int months= 5;
long time = 10;

FirebaseDatabase database = FirebaseDatabase.getInstance("db-uri");
DatabaseReference myRef = database.getReference().child("Records");

myRef.limitToLast(1).addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
        if(dataSnapshot.exists()){

            int last_db_user = dataSnapshot.child("id").getValue(Integer.class);
            int new_user = last_db_user++;

            //The User class is just a class that helps setting the values in the db                    
            User user = new User(new_user, name, months, time);

            String key = String.valueOf(new_user);
            myRef.child(key).setValue(user);
        }
    }

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

    }

我也试过像下面这样写,但是尽管这次它进入了 addListenerForSingleValueEvent(),它却说它不能执行 toInteger() 方法,因为对象是空的。

myRef.child("Records").limitToLast(1).addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
        if(dataSnapshot.exists()){

            int last_db_user = dataSnapshot.child("id").getValue(Integer.class);
            int new_user = last_db_user++;

            //The User class is just a class that helps setting the values in the db                    
            User user = new User(new_user, name, months, time);

            String key = String.valueOf(new_user);
            myRef.child(key).setValue(user);
        }
    }

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

    }

关于如何完成这项工作的任何想法?

更新

String name = Joe;
int months= 5;
long time = 10;

FirebaseDatabase database = FirebaseDatabase.getInstance("db-uri");
DatabaseReference myRef = database.getReference().child("Records");
       
       
myRef.orderByChild("id").limitToLast(1).addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                if(dataSnapshot.exists()){
                    for (DataSnapshot snapshot: dataSnapshot.getChildren()) {
                        int last_db_user = snapshot.child("id").getValue(Integer.class);
                        int new_user = last_db_user++;

                        //The User class is just a class that helps setting the values in the db
                        User user = new User(new_user, name, months, time);

                        String key = String.valueOf(new_user);
                        myRef.child(key).setValue(user);
                    }
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {
                throw databaseError.toException();
            }
        });

使用此代码,我得到以下异常:

E/AndroidRuntime: 致命异常: main 进程:com.example.app,PID:28429 java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“int java.lang.Integer.intValue()” 在 game.GameLogic$1.onDataChange(GameLogic.java:318) 在 com.google.firebase.database.core.ValueEventRegistration.fireEvent(com.google.firebase:firebase-database@@19.2.1:75) 在 com.google.firebase.database.core.view.DataEvent.fire(com.google.firebase:firebase-database@@19.2.1:63) 在 com.google.firebase.database.core.view.EventRaiser$1.run(com.google.firebase:firebase-database@@19.2.1:55) 在 android.os.Handler.handleCallback(Handler.java:900) 在 android.os.Handler.dispatchMessage(Handler.java:103) 在 android.os.Looper.loop(Looper.java:219) 在 android.app.ActivityThread.main(ActivityThread.java:8393) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1055)

【问题讨论】:

  • 请删除图片并以纯文本添加相关信息。

标签: java android firebase firebase-realtime-database


【解决方案1】:

它没有给我任何错误

嗯,这可能是因为您忽略了错误。请始终实现onCancelled,它至少应该是:

public void onCancelled(@NonNull DatabaseError databaseError) { 
    throw databaseError.toException(); 
}

第二个问题是您没有订购任何东西,这使得不清楚limitToLast(1) 实际在做什么。虽然这可能有效,但您应该始终指定排序。好像是这样:

myRef.orderByChild("id").limitToLast(1).addListenerForSingleValueEvent(new ValueEventListener() {
    ...

下一个问题:当您对 Firebase 数据库执行查询时,可能会有多个结果。所以快照包含这些结果的列表。即使只有一个结果,快照也会包含一个结果列表。

您需要在onDataChange 中通过循环snapshot.getChildren() 来处理此列表。所以:

myRef.limitToLast(1).addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
        for (DataSnapshot snapshot: dataSnapshot.getChildren()) { // ?
            int last_db_user = snapshot.child("id").getValue(Integer.class);
            int new_user = last_db_user++;

            //The User class is just a class that helps setting the values in the db                    
            User user = new User(new_user, name, months, time);

            String key = String.valueOf(new_user);
            myRef.child(key).setValue(user);
        }
    }

【讨论】:

  • 感谢您的帮助!我实现了你所有的建议,但现在我得到了这个异常: E/AndroidRuntime: "FATAL EXCEPTION: main Process: com.example.unilife, PID: 18542 java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang .Integer.intValue()' 在空对象引用上..."
  • 这听起来像是来自代码中的不同位置,所以您可能想用自己的MCVE 发布一个新问题。不过在此之前,请务必检查stackoverflow.com/questions/218384/…,因为这是一个非常常见的错误,故障排除总是非常相似。
  • 表示异常发生在以下行: int last_db_user = snapshot.child("id").getValue(Integer.class);这与我在发布的第二版代码中遇到的错误基本相同:\
  • 该代码缺少我在上一个 sn-p 中添加的循环。你确定你更新了代码然后从孩子snapshot那里得到值吗?
  • 我刚刚更新了问题,以便您可以看到我是如何编写代码的,因为它给了我异常。我犯了什么错误吗?
猜你喜欢
  • 1970-01-01
  • 2017-10-06
  • 1970-01-01
  • 2019-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-16
  • 2020-12-09
相关资源
最近更新 更多