DatabaseException:无法将类型为 java.lang.String 的对象转换为类型

新手上路,请多包涵

我已经查看了类似问题的其他一些答案,但不明白为什么我的答案不起作用。

我正在尝试让我的应用程序从 Firebase 读取命令并移动无人机。 firebase 中的命令来自一个单独的软件。该应用程序基于 Parrot Drone SDK 示例代码构建。

它似乎能够从命令对象中获取文本并将其附加到文本视图,但是当添加新的子项时它就会崩溃。添加新孩子时出现此错误。

 E/AndroidRuntime: FATAL EXCEPTION: main
                Process: com.parrot.sdksample, PID: 10592
                com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type com.parrot.sdksample.activity.CommandObject
                    at com.google.android.gms.internal.zg.zzb(Unknown Source)
                    at com.google.android.gms.internal.zg.zza(Unknown Source)
                    at com.google.firebase.database.DataSnapshot.getValue(Unknown Source)
                    at com.parrot.sdksample.activity.MiniDroneActivity$13.onChildAdded(MiniDroneActivity.java:383)
                    at com.google.android.gms.internal.px.zza(Unknown Source)
                    at com.google.android.gms.internal.vj.zzHX(Unknown Source)
                    at com.google.android.gms.internal.vp.run(Unknown Source)
                    at android.os.Handler.handleCallback(Handler.java:739)
                    at android.os.Handler.dispatchMessage(Handler.java:95)
                    at android.os.Looper.loop(Looper.java:148)
                    at android.app.ActivityThread.main(ActivityThread.java:5417)
                    at java.lang.reflect.Method.invoke(Native Method)
                    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

下面是我在 firebase 中的数据结构示例。

 {
"drones" : {
    "commands" : {
    "-L-n9HwaQktOdI2VEVlH" : {
        "executed" : false,
        "text" : "TAKE_OFF",
        "timestamp" : 1.512686825309134E9
    },
    "-L-nAuK5Ifde7Cdnan8K" : {
        "executed" : false,
        "text" : "LAND",
        "timestamp" : 1.512687248764272E9
    }
    }
}
}

我的活动中从 firebase 获取数据的功能如下所示。

 private void initFirebase(){
        mCommandTextView = (TextView) findViewById(R.id.commandTextView);

        FirebaseDatabase database = FirebaseDatabase.getInstance();
        DatabaseReference commandsRef = database.getReference("drones/commands");

        ChildEventListener childEventListener = new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
                Log.d(TAG, "onChildAdded:" + dataSnapshot.getKey());
                CommandObject command = dataSnapshot.getValue(CommandObject.class);
                mCommandTextView.append(command.text + "\n");
// I've tried commenting out the if statements below this, but it doesn't seem to make a difference.
                if ("TAKE_OFF".equals(command.text)) {
                    mMiniDrone.takeOff();
                } else if ("LAND".equals(command.text)) {
                    mMiniDrone.land();
                }
            }

            @Override
            public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName){

            }

            @Override
            public void onChildRemoved(DataSnapshot dataSnapshot) {

            }

            public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName){

            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        };
        commandsRef.addChildEventListener(childEventListener);
    }

我的 CommandObject 类看起来像这样。

 public class CommandObject {
    public String text;
    public float timestamp;
    public boolean executed;

    public CommandObject() {
    }

    public CommandObject(boolean executed, String text, float timestamp){
        this.executed = executed;
        this.text = text;
        this.timestamp = timestamp;
    }
}

我也尝试过使用值事件侦听器,但出现了同样的问题。

原文由 Desmond Chin 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 417
2 个回答

您收到此错误:

 Can't convert object of type java.lang.String to type com.parrot.sdksample.activity.CommandObject

因为您正在尝试读取 --- 类型的数据 String CommandObject 就是您收到此错误的原因。

获取这些值的更简单方法是使用 String 类,如下所示:

 DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference commandsRef = rootRef.child("drones").child("commands");
ValueEventListener eventListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for(DataSnapshot ds : dataSnapshot.getChildren()) {
            boolean executed = ds.child("executed").getValue(Boolean.class);
            String text = ds.child("text").getValue(String.class);
            double timestamp = ds.child("timestamp").getValue(Double.class);
            Log.d("TAG", executed + " / " + text + " / " + timestamp);
        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {}
};
commandsRef.addListenerForSingleValueEvent(eventListener);

而这种方法使用 CommandObject 类的对象:

 DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference commandsRef = rootRef.child("drones").child("commands");
ValueEventListener eventListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for(DataSnapshot ds : dataSnapshot.getChildren()) {
            CommandObject commandObject = ds.getValue(CommandObject.class);
            Log.d("TAG", commandObject.getExecuted() + " / " +
                commandObject.getText() + " / " +
                commandObject.getTimestamp());
        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {}
};
commandsRef.addListenerForSingleValueEvent(eventListener);

在这两种情况下,您的输出将是:

 false / TAKE_OFF / 1.512686825309134E9
false / LAND / 1.512687248764272E9

原文由 Alex Mamo 发布,翻译遵循 CC BY-SA 3.0 许可协议

Alex 提供的解决方案有效但没有完全回答为什么我无法将我的数据存储在对象中,而对于我的应用程序,当孩子添加监听器时,该应用程序能够读取 Firebase 上已有的数据,但当新的添加了子项,值为空。

     onChildAdded:DataSnapshot { key = -L0JjGo-3QMYDsuTMQcN, value =  }

我做了更多的挖掘以找出可能导致此问题的原因,并发现这可能是因为值不是同时写入的。查看 firebase 似乎先添加了键,然后添加了值。这就是错误说无法转换的原因,因为它不存在。我正在使用 Python Firebase Admin SDK 将数据添加到 Firebase,所以我不确定这是否是原因所在。

因此,为了解决我的问题,我将代码移至 onChildChanged 函数并添加了一个检查,以便代码仅在我需要的所有数据都存在时运行。这样我就可以立即获取存储在对象中的值。

     @Override
    public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName){
        if (dataSnapshot.child("text").exists() &&
                dataSnapshot.child("executed").exists() &&
                dataSnapshot.child("timestamp").exists()){
            Log.d(TAG, "onChildChanged:" + dataSnapshot.toString());
            CommandObject command = dataSnapshot.getValue(CommandObject.class);
            if ("TAKE_OFF".equals(command.text)) {
                mMiniDrone.takeOff();
            } else if ("LAND".equals(command.text)) {
                mMiniDrone.land();
            }
        }
    }

原文由 Desmond Chin 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题