2016-12-31 1 views
2

Ich habe eine Geofire Firebase Standortklasse erstellt. Ich kann Teilnehmerschlüssel aus der Standorttabelle lesen. Aber, jetzt möchte ich Abonnententabelle abfragen, um komplettes Teilnehmerobjekt zu erhalten.2. Ebene Callback in Android funktioniert nicht für verschachtelte Abfragen

Inside-Methode OnGeoQueryReady, ich habe alle Teilnehmerschlüssel. Aber wenn ich einen Aufruf an die Abonnententabelle innerhalb der onGeoQueryReady-Methode abrichte, wird nichts zurückgegeben.

public void findNearBySubscribers(final LocationInterface locationInterface, double radius, double clatitude, double clongitude){ 
     DatabaseReference ref = FirebaseDatabase.getInstance().getReference("location/"); 
     GeoFire geoFire = new GeoFire(ref); 
     final ArrayList<String> keys = new ArrayList<String>(); 
     GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(clatitude, clongitude), radius); 
     geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() { 
      @Override 
      public void onKeyEntered(String key, GeoLocation location) { 
       keys.add(key); 
      } 

      @Override 
      public void onKeyExited(String key) { 
       System.out.println(String.format("Key %s is no longer in the search area", key)); 
      } 

      @Override 
      public void onKeyMoved(String key, GeoLocation location) { 

      } 

      @Override 
      public void onGeoQueryReady() { 

       locationInterface.getNearBySubscribersCallback(keys); 
      } 

      @Override 
      public void onGeoQueryError(DatabaseError error) { 
       System.err.println("There was an error with this query: " + error); 
      } 
     }); 
    } 

Unter den Code zu finden Abonnenten basierend auf Schlüsseln funktioniert nicht. Die Größe der Teilnehmerliste ist Null, aber die Antwortzeichenfolge hat einen Wert. Kann mir jemand dabei helfen? sieht wie folgt ein 2-Ebene Rückruf ist ...

public void findNearBySubscribers(final LocationInterface locationInterface, double radius, double clatitude, double clongitude){ 
     DatabaseReference ref = FirebaseDatabase.getInstance().getReference("location/"); 
     GeoFire geoFire = new GeoFire(ref); 
     final ArrayList<String> keys = new ArrayList<String>(); 
     GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(clatitude, clongitude), radius); 
     geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() { 
      @Override 
      public void onKeyEntered(String key, GeoLocation location) { 
       keys.add(key); 
      } 

      @Override 
      public void onKeyExited(String key) { 
       System.out.println(String.format("Key %s is no longer in the search area", key)); 
      } 

      @Override 
      public void onKeyMoved(String key, GeoLocation location) { 

      } 

      @Override 
      public void onGeoQueryReady() { 
       final ArrayList<Subscriber> subscriberList = new ArrayList<Subscriber>(); 

       for(String key: keys) { 
        String url = "https://moe-90cc7.firebaseio.com/subscriber/"; 
        String uri = url + key + ".json"; 
        RestClient.get(uri, null, new TextHttpResponseHandler() { 
         @Override 
         public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) { 
         } 

         @Override 
         public void onSuccess(int statusCode, Header[] headers, String responseString) { 
          Gson gson = new Gson(); 
          Subscriber subscriber = gson.fromJson(responseString, Subscriber.class); 
          System.out.println("Response Str" + responseString); 
          subscriberList.add(subscriber); 
         } 
        }); 
       } 
       System.out.println("List size "+subscriberList.size()); 
       locationInterface.getNearBySubscribersCallback(keys); 
      } 

      @Override 
      public void onGeoQueryError(DatabaseError error) { 
       System.err.println("There was an error with this query: " + error); 
      } 
     }); 
    } 

TRIED Red Pill WEISE DEN - aber seine ARBEITEN FÜR MICH NICHT. Grundsätzlich versuche ich einen Teilnehmer zu laden, wenn ein Teilnehmerschlüssel verfügbar ist.

package app.com.date.services; 

import com.firebase.geofire.GeoFire; 
import com.firebase.geofire.GeoLocation; 
import com.firebase.geofire.GeoQuery; 
import com.firebase.geofire.GeoQueryEventListener; 
import com.google.firebase.database.DatabaseError; 
import com.google.firebase.database.DatabaseReference; 
import com.google.firebase.database.FirebaseDatabase; 
import com.google.gson.Gson; 
import com.loopj.android.http.TextHttpResponseHandler; 

import java.util.ArrayList; 
import java.util.concurrent.Semaphore; 

import app.com.date.subscriber.Subscriber; 
import cz.msebera.android.httpclient.Header; 

public class LocationService { 
    private ArrayList<Subscriber> subscriberList = new ArrayList<Subscriber>(); 

    public void addGeoLocation(final LocationInterface locationInterface, String subscriberId, double latitude, double longitude) { 

     DatabaseReference ref = FirebaseDatabase.getInstance().getReference("location/"); 
     GeoFire geoFire = new GeoFire(ref); 
     geoFire.setLocation(subscriberId, new GeoLocation(latitude, longitude), new GeoFire.CompletionListener() { 
      @Override 
      public void onComplete(String key, DatabaseError error) { 
       if (key != null) { 
        locationInterface.addLocationCallback(true); 
       } else { 
        locationInterface.addLocationCallback(false); 
       } 
      } 
     }); 
    } 

    public void findNearBySubscribers(final LocationInterface locationInterface, double radius, double clatitude, double clongitude) { 
     DatabaseReference ref = FirebaseDatabase.getInstance().getReference("location/"); 
     GeoFire geoFire = new GeoFire(ref); 
     final ArrayList<String> keys = new ArrayList<String>(); 
     final ArrayList<Subscriber> subscriberList = new ArrayList<Subscriber>(); 
     GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(clatitude, clongitude), radius); 
     geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() { 
      @Override 
      public void onKeyEntered(String key, GeoLocation location) { 
       String url = "https://moe-90cc7.firebaseio.com/subscriber/"; 
       String uri = url + key + ".json"; 
       RestClient.get(uri, null, new TextHttpResponseHandler() { 
        @Override 
        public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) { 
        } 
        @Override 
        public void onSuccess(int statusCode, Header[] headers, String responseString) { 
         Gson gson = new Gson(); 
         Subscriber subscriber = gson.fromJson(responseString, Subscriber.class); 
         System.out.println("Response Str" + responseString); 
         subscriberList.add(subscriber); 
        } 
       }); 

       System.out.println("onKeyEntered list "+subscriberList.size()); 

      } 

      @Override 
      public void onKeyExited(String key) { 
       System.out.println(String.format("Key %s is no longer in the search area", key)); 
      } 

      @Override 
      public void onKeyMoved(String key, GeoLocation location) { 

      } 

      @Override 
      public void onGeoQueryReady() { 
       System.out.println("onGeoQueryReady list "+subscriberList.size()); 
      } 

      @Override 
      public void onGeoQueryError(DatabaseError error) { 
       System.err.println("There was an error with this query: " + error); 
      } 
     }); 
    } 
} 

OUTPUT

12-31 17:57:34.090 13956-14019/app.com.date V/FA: Processing queued up service tasks: 3 
12-31 17:57:34.366 13956-13956/app.com.date I/System.out: onKeyEntered list 0 
12-31 17:57:34.366 13956-13956/app.com.date I/System.out: onKeyEntered list 0 
12-31 17:57:34.366 13956-13956/app.com.date I/System.out: onGeoQueryReady list 0 
12-31 17:57:34.456 13956-13956/app.com.date V/AsyncHttpRH: Progress 332 from 332 (100%) 
12-31 17:57:34.475 13956-13956/app.com.date I/System.out: Response Str{"age":29,"alcohol":false,"animalLover":false,"children":false,"id":"GYlSDXx0Kwh7AerOzFGf8MDmhOg1","isEmpty":false,"mainImage":"https://firebasestorage.googleapis.com/v0/b/moe-erOzFGf8MDmhOg1%2F1265290048?alt=media&token=80ab1410-bac9-4679-a3d4-152204319310","name":"singh","smoker":false} 
12-31 17:57:34.574 13956-13956/app.com.date V/AsyncHttpRH: Progress 327 from 327 (100%) 
12-31 17:57:34.584 13956-13956/app.com.date I/System.out: Response Str{"age":65,"alcohol":false,"animalLover":false,"children":false,"id":"xZWPMjWQCYY4xNimx3WHqVZcQxs1","isEmpty":false,"mainImage":"https://firebasestorage.googleapQCYY4xNimx3WHqVZcQxs1%2F1405868067?alt=media&token=b8d128a6-7156-42e8-9d0b-953feb128b4c","name":" Singh","smoker":false} 
12-31 17:57:39.123 13956-14019/app.com.date V/FA: Inactivity, disconnecting from the service 

Antwort

1

Das Problem ist in diesem Code:

final ArrayList<Subscriber> subscriberList = new ArrayList<Subscriber>(); 

for(String key: keys) { 
    String url = "https://moe-90cc7.firebaseio.com/subscriber/"; 
    String uri = url + key + ".json"; 
    RestClient.get(uri, null, new TextHttpResponseHandler() { 
     @Override 
     public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) { 
     } 

     @Override 
     public void onSuccess(int statusCode, Header[] headers, String responseString) { 
      Gson gson = new Gson(); 
      Subscriber subscriber = gson.fromJson(responseString, Subscriber.class); 
      System.out.println("Response Str" + responseString); 
      subscriberList.add(subscriber); 
     } 
    }); 
} 
System.out.println("List size "+subscriberList.size()); 
locationInterface.getNearBySubscribersCallback(keys); 

Die Daten asynchron von Firebase beladen ist. Dies bedeutet, dass Sie bis zum Drucken der subscriberList.size() noch keine Abonnenten geladen haben.

Dies ist am einfachsten zu sehen, ob Sie den Code zur Ausgabe einige einfache Protokollierung-Anweisungen ändern:

final ArrayList<Subscriber> subscriberList = new ArrayList<Subscriber>(); 

System.out.println("Before starting to load"); 
for(String key: keys) { 
    String url = "https://moe-90cc7.firebaseio.com/subscriber/"; 
    String uri = url + key + ".json"; 
    RestClient.get(uri, null, new TextHttpResponseHandler() { 
     @Override 
     public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) { 
     } 

     @Override 
     public void onSuccess(int statusCode, Header[] headers, String responseString) { 
      Gson gson = new Gson(); 
      Subscriber subscriber = gson.fromJson(responseString, Subscriber.class); 
      System.out.println("Response Str" + responseString); 
      subscriberList.add(subscriber); 
      System.out.println("In onSuccess, list size "+subscriberList.size()); 
     } 
    }); 
} 
System.out.println("After starting to load, list size "+subscriberList.size()); 
locationInterface.getNearBySubscribersCallback(keys); 

Der Ausgang dieses sein wird:

Bevor

zu laden beginnen Nach beginnt zu laden, Listengröße 0

In onSuccess, Listengröße 1

In onSuccess, Liste Größe 2

...

So können Sie die der Code in onSuccess() läuft nach der Code weiter unten in der Datei. Denken Sie daran: Dies liegt daran, dass die Daten asynchron geladen werden und ein völlig normales Verhalten im Umgang mit modernen Web-/Cloud-APIs vorliegt.

Die Lösung besteht darin, Ihr Problem neu zu definieren. Anstatt zu sagen, "lade zuerst die Teilnehmer, dann tue xyz mit ihnen", versuche dein Problem auf "immer wenn die Teilnehmer sich geändert haben, zu tun, tue xyz mit ihnen".

Die Implementierung ist, dass Sie den Code bewegen, die etwas zu den Teilnehmern in die onSuccess Handler tut, wie ich mit Druck die Länge der Teilnehmerliste gemacht haben.

+0

Danke für die Antwort, das Problem ist, ich rufe diese Methode von einer anderen Aktivität und ich brauche eine Abonnentenliste in dieser Aktivität verfügbar, um die Listenansicht zu füllen. – user7327850

+0

So kann ich nichts in der Methode onsucces tun, ich möchte der Rückruf Liste der Abonnenten zurückgeben. – user7327850

+0

Sie können nicht etwas zurückgeben, das noch nicht geladen wurde. Und Sie können die Methode nicht auf Android warten lassen (und auch nicht wollen). Siehe http://stackoverflow.com/questions/33203379/setting-singleton-property-value-in-firebase-listener. Wenn Sie das Problem jedoch neu gestalten, können Sie "die Abonnentenliste laden und dann die Listenansicht auffüllen, sobald die Abonnenten geladen sind". –

Verwandte Themen