2015-06-05 17 views
9

Ich möchte eine Methode erstellen, die einen child Wert in FireBase zurückgibt. Ich habe versucht, so etwas zu tun:warten, bis firebase Daten abruft

public String getMessage(){ 

    root.child("MessagesOnLaunch").child("Message").addListenerForSingleValueEvent(new ValueEventListener() { 
     @Override 
     public void onDataChange(DataSnapshot dataSnapshot) { 
      message = (String) dataSnapshot.getValue(); 
      Log.i("4r398", "work"); 
     } 

     @Override 
     public void onCancelled(FirebaseError firebaseError) { 
      Log.e("error", firebaseError.getMessage()); 
     } 
    }); 
    return message; 
} 

Das Problem ist, dass die Methode gibt null, die wahrscheinlich ist, dass das Verfahren, bis die Zuhörer beendet wartet nicht, und das Rück null weil sein Standardwert von message. Wie kann ich diese Methode warten, bis der Listener auftritt und dann den Wert zurückgeben.

+0

davon ausgehen, dass der Stamm in der Klasse gespeichert ist (und die Klasse nicht gc'ed ist), sollte es keine Rolle spielen, dass die Funktion beendet wird –

+1

Sie können keinen asynchronen Wert synchron zurückgeben. Die "message" -Variable ist hier völlig sinnlos, da sie zum Zeitpunkt der Rückgabe nicht gesetzt wird - die Daten müssen zuerst vom Server geholt werden. Stattdessen sollte getMessage() entweder einen Callback irgendeiner Art akzeptieren oder ein Event auslösen. Es gibt [eine Anleitung zu diesen Konzepten] (https://www.firebase.com/docs/android/), voller Beispiele und Ratschläge. – Kato

+0

[Diese Antwort verwenden] (http://stackoverflow.com/a/38542796/4882204). Ich habe das gleiche Problem gesehen und mit EventBus gelöst. –

Antwort

2

Verwenden Sie Firebase nicht als Funktionen, die Werte zurückgeben - es ist gegen seine asynchrone Natur.

Planen Sie die Codestruktur, die es Firebase ermöglicht, ihre Aufgabe auszuführen, und gehen Sie dann innerhalb des Abschlusses (Block) zum nächsten Schritt.

Ändern Sie in Ihrem Code beispielsweise die Funktion so, dass nichts zurückgegeben wird, und rufen Sie innerhalb der onDataChange die letzte Funktion auf, um die Benutzeroberfläche zu aktualisieren.

3

Stellen eine Schnittstelle

public interface OnGetDataListener { 
    //this is for callbacks 
    void onSuccess(DataSnapshot dataSnapshot); 
    void onStart(); 
    void onFailure(); 
} 

die folgende Funktion readdata Deklarieren()

public void readData(Firebase ref, final OnGetDataListener listener) { 
    listener.onStart(); 
    ref.addListenerForSingleValueEvent(new ValueEventListener() { 
     @Override 
     public void onDataChange(DataSnapshot dataSnapshot) { 
      listener.onSuccess(dataSnapshot); 
     } 

     @Override 
     public void onCancelled(FirebaseError firebaseError) { 
      listener.onFailure(); 
     } 
    }); 

} 

Rufen Sie die readdata() Funktion wie

readData(root.child("MessagesOnLaunch").child("Message"), new OnGetDataListener() { 
       @Override 
       public void onSuccess(DataSnapshot dataSnapshot) { 

       //got data from database....now you can use the retrieved data 


       } 
       @Override 
       public void onStart() { 
        //when starting 
        Log.d("ONSTART", "Started"); 
       } 

       @Override 
       public void onFailure() { 
        Log.d("onFailure", "Failed"); 
       } 
      }); 

readdata() aufgerufen innerhalb werden folgendermaßen Ihre getMessage() -Methode oder sogar innerhalb onCreate()

+0

Ich folgte diesen Anweisungen bis zum Punkt, und ich habe immer noch das gleiche Problem wie OP. Ich verstehe nicht, wie ich meinen Code so strukturieren soll, dass ich die Daten in der Firebase-Datenbank verwenden kann – Flaom