Android Firebase从子节点检索数据

时间:2016-07-24 10:25:08

标签: android firebase firebase-realtime-database

我正在尝试从Firebase子节点获取数据。但它会引发Can't convert object of type java.lang.String to type uk.co.stableweb.geethika.model.DailyVerse异常。

这是我的Firebase数据库的结构。

Firebase database structure.

这是代码。我正在使用Android Firebase新版documentation

mRef = FirebaseDatabase.getInstance().getReference().child("daily_verse");
mRef.keepSynced(true);

ChildEventListener childEventListener = new ChildEventListener() {
    @Override
    public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
        Log.d("Child Event,Verse", dataSnapshot.getKey());

        dailyVerse = dataSnapshot.getValue(DailyVerse.class);

    }

    @Override
    public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) {
        Log.d("Child Event,Verse", "onChildChanged:" + dataSnapshot.getKey());

        dailyVerse = dataSnapshot.getValue(DailyVerse.class);
    }

    @Override
    public void onChildRemoved(DataSnapshot dataSnapshot) {

    }

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

    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        Log.w("Firebase", "onCancelled", databaseError.toException());
        Toast.makeText(context, "Failed to load verse",
                Toast.LENGTH_SHORT).show();
    }
};

mRef.addChildEventListener(childEventListener);

和Model class。

public class DailyVerse {

    private String verse_title;
    private String verse_content;

    public String getVerseTitle() {
        return verse_title;
    }

    public void setVerseTitle(String verse_title) {
        this.verse_title = verse_title;
    }

    public String getVerseContent() {
        return verse_content;
    }

    public void setVerseContent(String verse_content) {
        this.verse_content = verse_content;
    }
}

和LogCat。

com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type uk.co.stableweb.geethika.model.DailyVerse
  at com.google.android.gms.internal.zzalq.zzd(Unknown Source)
  at com.google.android.gms.internal.zzalq.zzb(Unknown Source)
  at com.google.android.gms.internal.zzalq.zza(Unknown Source)
  at com.google.firebase.database.DataSnapshot.getValue(Unknown Source)
  at uk.co.stableweb.geethika.VerseActivityFragment$1.onChildAdded(VerseActivityFragment.java:63)
  at com.google.android.gms.internal.zzahh.zza(Unknown Source)
  at com.google.android.gms.internal.zzajh.zzctc(Unknown Source)
  at com.google.android.gms.internal.zzajk$1.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:5461)
  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)

但是如果我按如下方式更改数据库引用。并获取dataSnapshot值,它会抓取数据。

mRef = FirebaseDatabase.getInstance().getReference("daily_verse");

testVal = (String) dataSnapshot.getValue();
Log.d("TEST", testVal);

V/FA: Activity resumed, time: 278033062
D/Child Event,Verse added: verse_content
D/TEST: විශ්වාසකමේ මාර්ගය තෝරා ගතිමි. ඔබගේ විනිශ්චයන් මා ඉදිරියෙහි තබා ගතිමි.
D/Child Event,Verse added: verse_title
D/TEST: ගීතාවලිය 119:30

我认为可以使用HashMap获取这些值。但有评论说不再推荐。

5 个答案:

答案 0 :(得分:5)

请注意JSON中属性的名称以及Java代码中的字段/ getter。如果它们不匹配,Firebase客户端将无法匹配它们之间的值。

您的JSON有verse_titleverse_content,因此您的Java类必须

public class DailyVerse {
    public String verse_title;
    public String verse_content;    
}

public class DailyVerse {

    private String verse_title;
    private String verse_content;

    public String getVerse_title() {
        return verse_title;
    }

    public void setVerse_title(String verse_title) {
        this.verse_title = verse_title;
    }

    public String getVerse_content() {
        return verse_content;
    }

    public void setVerse_content(String verse_content) {
        this.verse_content = verse_content;
    }
}

自Firebase Android SDK 9.2起,您还可以注释Java代码以映射到正确的JSON属性。因此,获得正确映射的第三种方法是:

public class DailyVerse {

    private String verse_title;
    private String verse_content;

    @PropertyName("verse_title")
    public String getVerseTitle() {
        return verse_title;
    }

    public void setVerseTitle(String verse_title) {
        this.verse_title = verse_title;
    }

    @PropertyName("verse_content")
    public String getVerseContent() {
        return verse_content;
    }

    public void setVerseContent(String verse_content) {
        this.verse_content = verse_content;
    }
}

我没有尝试过这个最新的版本,所以如果答案上有拼写错误,请告诉我。

答案 1 :(得分:3)

通过这种方法

mRef.addChildEventListener(childEventListener);

您订阅了

.child("daily_verse");

孩子。 daily_verse有两个孩子:verse_content和verse_title。这些孩子的类型是String。因此,您可以在onChildAdd侦听器中获得两个String数据快照。

<强>更新 尝试这样的事情:

mRef = FirebaseDatabase.getInstance().getReference();
mRef.keepSynced(true);

ChildEventListener childEventListener = new ChildEventListener() {
    @Override
    public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
        Log.d("Child Event,Verse", dataSnapshot.getKey());
        if ("daily_verse".equal(dataSnapshot().getKey){
            dailyVerse = dataSnapshot.getValue(DailyVerse.class);
            Log.d("TEST","Object: "+dailyVerse);
            if (dailyVerse!=null){
               Log.d("TEST","values: "+dailyVerse.verse_title+", "+dailyVerse.verse_content);
            }
        }

    }

    @Override
    public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) {
        Log.d("Child Event,Verse", "onChildChanged:" + dataSnapshot.getKey());
        if ("daily_verse".equal(dataSnapshot().getKey){
          dailyVerse = dataSnapshot.getValue(DailyVerse.class);
          Log.d("TEST","Changed object: "+dailyVerse);
          if (dailyVerse!=null){
             Log.d("TEST","Changed values: "+dailyVerse.verse_title+", "+dailyVerse.verse_content);
          }
        }
    }

    @Override
    public void onChildRemoved(DataSnapshot dataSnapshot) {

    }

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

    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        Log.w("Firebase", "onCancelled", databaseError.toException());
        Toast.makeText(context, "Failed to load verse",
                Toast.LENGTH_SHORT).show();
    }
};

mRef.addChildEventListener(childEventListener);

您应该订阅来自父对象的事件,并在事件监听器处检查密钥。

答案 2 :(得分:1)

DataRef = FirebaseDatabase.getInstance().getReference().child("Users");

DataRef.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                String acctname = (String)dataSnapshot.child("Name").getValue();
                String acctmail = (String)dataSnapshot.child("Email").getValue();

            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
});

答案 3 :(得分:1)

使用firebase模型类时,您必须包含一个空构造函数以供firebase使用。

尝试将其添加为

public class DailyVerse {
    public DailyVerse(){

    }
}

答案 4 :(得分:0)

ArrayList<EventsResponse> usersEventsList = new ArrayList<>();
    dummyIdsArrayList = new ArrayList<>();
    Iterator<DataSnapshot> eventsIterator = dataSnapshot.getChildren().iterator();
    while (eventsIterator.hasNext()) {
        DataSnapshot eventsSnapShot = eventsIterator.next();
        EventsResponse eventsResponse = new EventsResponse();
        eventsResponse.setEventName(eventsSnapShot.getKey());
        Iterator<DataSnapshot> eventChildIterator = eventsSnapShot.getChildren().iterator();
        while (eventChildIterator.hasNext()) {
            DataSnapshot eventchildSnapshot = eventChildIterator.next();
            if (eventchildSnapshot.getKey().equals("is_recursive")) {
                eventsResponse.setRecursive((Boolean) eventchildSnapshot.getValue());
            } else if (eventchildSnapshot.getKey().equals("is_notif")) {
                eventsResponse.setNotif((Boolean) eventchildSnapshot.getValue());
            } else if (eventchildSnapshot.getKey().equals("is_editable")) {
                eventsResponse.setEditable((Boolean) eventchildSnapshot.getValue());
            } else if (eventchildSnapshot.getKey().equals("is_visible")) {
                eventsResponse.setVisible((Boolean) eventchildSnapshot.getValue());
            } else if (eventchildSnapshot.getKey().equals("name")) {
                eventsResponse.setName(eventchildSnapshot.getValue().toString());
            } else if (eventchildSnapshot.getKey().equals("date")) {
                Iterator<DataSnapshot> eventChildDateIterator = eventchildSnapshot.getChildren().iterator();
                while (eventChildDateIterator.hasNext()) {
                    DataSnapshot eventchildDateSnapshot = eventChildDateIterator.next();
                    if (eventchildDateSnapshot.getKey().equals("day")) {
                        eventsResponse.setDay(eventchildDateSnapshot.getValue().toString());
                    } else if (eventchildDateSnapshot.getKey().equals("month")) {
                        eventsResponse.setMonth(eventchildDateSnapshot.getValue().toString());
                    } else if (eventchildDateSnapshot.getKey().equals("year")) {
                        eventsResponse.setYear(eventchildDateSnapshot.getValue().toString());
                    }
                }
            } else {
                eventsResponse.setNotif(true);
                eventsResponse.setVisible(false);
            }
        }

如果您无法获取数据,则可以获取该格式的数据。