2015-12-09 19 views
5

Sto tentando di restituire un valore che ottengo dal metodo onResponse nella richiesta di chiamata retrofit, esiste un modo per ottenere tale valore dal metodo sovrascritto? qui è il mio codice:Come posso restituire il valore dalla funzione onResponse of Retrofit?

public JSONArray RequestGR(LatLng start, LatLng end) 
    { 
     final JSONArray jsonArray_GR; 

     EndpointInterface loginService = ServiceAuthGenerator.createService(EndpointInterface.class);  
     Call<GR> call = loginService.getroutedriver(); 
     call.enqueue(new Callback<GR>() { 
      @Override 
      public void onResponse(Response<GR> response , Retrofit retrofit) 
      { 

       jsonArray_GR = response.body().getRoutes(); 
//i need to return this jsonArray_GR in my RequestGR method 
      } 
      @Override 
      public void onFailure(Throwable t) { 
      } 
     }); 
     return jsonArray_GR; 
    } 

non riesco a ottenere il valore di jsonArray_GR perché per essere in grado di utilizzarlo in onResponse metodo ho bisogno di dichiararlo finale e non posso dargli un valore.

risposta

9

Il problema è che si sta tentando di restituire in modo sincrono il valore di enqueue, ma si tratta di un metodo asincrono che utilizza una richiamata, pertanto non è possibile farlo. Hai 2 opzioni:

  1. È possibile cambiare il metodo di RequestGR ad accettare un callback e quindi catena enqueue richiamata ad esso. Questo è simile al mapping in framework come rxJava.

Questo apparirebbe meno così:

public void RequestGR(LatLng start, LatLng end, final Callback<JSONArray> arrayCallback) 
    { 

     EndpointInterface loginService = ServiceAuthGenerator.createService(EndpointInterface.class);  
     Call<GR> call = loginService.getroutedriver(); 
     call.enqueue(new Callback<GR>() { 
      @Override 
      public void onResponse(Response<GR> response , Retrofit retrofit) 
      { 

       JSONArray jsonArray_GR = response.body().getRoutes(); 
       arrayCallback.onResponse(jsonArray_GR); 
      } 
      @Override 
      public void onFailure(Throwable t) { 
       // error handling? arrayCallback.onFailure(t)? 
      } 
     }); 
    } 

L'avvertenza di questo approccio è semplicemente spinge la roba asincrona su un altro livello, che potrebbe essere un problema per voi.

  1. È possibile utilizzare un oggetto simile ad un BlockingQueue, Promise o un anche il proprio oggetto Observable o il contenitore (attenzione per essere thread-safe) che permette di controllare e impostare il valore .

Questo sarebbe simile:

public BlockingQueue<JSONArray> RequestGR(LatLng start, LatLng end) 
    { 
     // You can create a final container object outside of your callback and then pass in your value to it from inside the callback. 
     final BlockingQueue<JSONArray> blockingQueue = new ArrayBlockingQueue<>(1); 
     EndpointInterface loginService = ServiceAuthGenerator.createService(EndpointInterface.class);  
     Call<GR> call = loginService.getroutedriver(); 
     call.enqueue(new Callback<GR>() { 
      @Override 
      public void onResponse(Response<GR> response , Retrofit retrofit) 
      { 

       JSONArray jsonArray_GR = response.body().getRoutes(); 
       blockingQueue.add(jsonArray_GR); 
      } 
      @Override 
      public void onFailure(Throwable t) { 
      } 
     }); 
     return blockingQueue; 
    } 

È possibile quindi modo sincrono attendere il risultato nel vostro metodo chiamante in questo modo:

BlockingQueue<JSONArray> result = RequestGR(42,42); 
JSONArray value = result.take(); // this will block your thread 

Consiglio vivamente la lettura su un quadro simile rxJava però.

+0

Non posso usare la soluzione nel retrofit 2.0. @torbinksy puoi aiutarmi? – wanz

+0

@wanz Non riuscivo a farlo funzionare con rf 2.0 ... ti farò sapere se/quando avrò una soluzione funzionante – JC23

+0

@ JC23 grazie mille per il tuo aiuto, ho chiesto prima e qualcuno mi risponderà http: //stackoverflow.com/a/37142046/4226651 ma non so ancora come usarlo – wanz

Problemi correlati