【问题标题】:Retrieving nested data in Firebase - Android在 Firebase 中检索嵌套数据 - Android
【发布时间】:2017-02-16 22:33:01
【问题描述】:

我刚刚进入了 firebase 和 android 的世界。我按照在线教程设置和获取非嵌套数据并将其显示在列表视图中,如下所示:

数据前:

    mListView = (ListView) findViewById(R.id.ListView) ;
    final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mStudents);
    mListView.setAdapter(arrayAdapter);
    FirebaseDatabase database = FirebaseDatabase.getInstance();
    myRef = database.getReference().child("Student1");
    myRef.addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s) {
            String value = dataSnapshot.getValue(String.class);
            String key = dataSnapshot.getKey();
            String totl = key + ": " + value;
            mStudents.add(totl);
            arrayAdapter.notifyDataSetChanged();
        }
    });

我在数据库中添加了一个带有子字段的成绩字段。我想显示整个 student1 数据以及成绩。当我尝试运行上面的代码时。我收到以下错误。

数据后:

FATAL EXCEPTION: main
              Process: com.adcpnmd.mystudents, PID: 3524
              com.google.firebase.database.DatabaseException: Failed to convert value of type java.util.HashMap to String
                  at com.google.android.gms.internal.zzbqi.zzaD(Unknown Source)
                  at com.google.android.gms.internal.zzbqi.zzb(Unknown Source)
                  at com.google.android.gms.internal.zzbqi.zza(Unknown Source)
                  at com.google.firebase.database.DataSnapshot.getValue(Unknown Source)
                  at com.adcpnmd.mystudents.Main$1.onChildAdded(Main.java:39)
                  at com.google.android.gms.internal.zzblz.zza(Unknown Source)
                  at com.google.android.gms.internal.zzbnz.zzYj(Unknown Source)
                  at com.google.android.gms.internal.zzboc$1.run(Unknown Source)
                  at android.os.Handler.handleCallback(Handler.java:751)
                  at android.os.Handler.dispatchMessage(Handler.java:95)
                  at android.os.Looper.loop(Looper.java:154)
                  at android.app.ActivityThread.main(ActivityThread.java:6077)
                  at java.lang.reflect.Method.invoke(Native Method)
                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)

我应该怎么做才能访问整个数据并添加到我的 ListView ?还是我的数据结构不正确?

提前致谢。

【问题讨论】:

标签: android firebase firebase-realtime-database


【解决方案1】:

尝试像这样更改您的 firebase 代码:

myRef = database.getReference().child("Student1").child("Grades");
myRef.addChildEventListener(new ChildEventListener() {
    @Override
    public void onChildAdded(DataSnapshot dataSnapshot, String s) {
        if (dataSnapshot.exists()) {
            String value = dataSnapshot.getValue(String.class);
            String key = dataSnapshot.getKey();
            String totl = key + ": " + value;
            mStudents.add(totl);
            arrayAdapter.notifyDataSetChanged();
        }
    }
});

更新

要访问整个节点Student1,可以这样:

首先,我已将您的Class 字段重命名为Course,因为Class 可能会产生混淆和问题(Android 本身使用它)。因此,使用代表您的数据的普通对象创建一个 Java 文件 Student.java

public class Student {

    private String Course;
    private String Name;
    private String Percentile;
    private HashMap<String,String> Grades;

    public Student() {

    }

    public Student(String course, String name, String percentile, HashMap<String, String> grades) {
        Course = course;
        Name = name;
        Percentile = percentile;
        Grades = grades;
    }

    public String getCourse() {
        return Course;
    }

    public String getName() {
        return Name;
    }

    public String getPercentile() {
        return Percentile;
    }

    public HashMap<String, String> getGrades() {
        return Grades;
    }
}

接下来,要获取数据,这样做:

ValueEventListener valueEventListener = new ValueEventListener() {

            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                Student student = dataSnapshot.getValue(Student.class);

                Log.d("TAG","name: "+student.getName());
                Log.d("TAG","percentile: "+student.getPercentile());
                Iterator it = student.getGrades().entrySet().iterator();
                while (it.hasNext()) {
                    Map.Entry pair = (Map.Entry)it.next();
                    Log.d("TAG","grade: "+pair.getKey() +  " = "  + pair.getValue());
                    it.remove(); // avoids a ConcurrentModificationException
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        };

myRef = database.getReference().child("Student1");
myRef.addListenerForSingleValueEvent(valueEventListener);

【讨论】:

  • 这只能让我访问成绩字段内的数据。我想访问整个 Student1 数据以进行显示。姓名,班级,百分位数以及成绩。我怎样才能做到这一点?
  • addListenerForSingleValueEvent(valueEventListener) 和 addChildEventListener(childEventListener) 有什么区别?
  • addListenerForSingleValueEvent 触发一次,然后不再触发:ValueEventListener 内部用于读取和侦听路径全部内容的更改。 addChildEventListenerChildEventListener 附加到位置:内部的ChildEventListener 用于接收有关给定DatabaseReference 的子位置更改的事件。你可以在这里阅读更多:firebase.google.com/docs/reference/android/com/google/firebase/… 和这里:firebase.google.com/docs/database/android/read-and-write
  • @ValentinoS。我正在尝试解决类似的问题,但出现数据库异常。请查看我的帖子@stackoverflow.com/questions/46314380/…
猜你喜欢
  • 2021-01-08
  • 2017-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-12
  • 1970-01-01
  • 2017-11-29
相关资源
最近更新 更多