2015-01-27 15 views
16

Ciao Vorrei modularizzare le richieste di volley in modo da non mischiare il codice di presentazione dell'attività con le richieste di scarica. Tutti gli esempi che ho visto, la richiesta di scarica viene posizionata, ad esempio, sull'evento OnClick da un pulsante di attività.Android Volley - Come isolare le richieste in un'altra classe

voglio dire questo codice (tratto da fonte diff):

// prepare the Request 
JsonObjectRequest getRequest = new JsonObjectRequest(Request.Method.GET, url, null, 
    new Response.Listener<JSONObject>() 
    { 
     @Override 
     public void onResponse(JSONObject response) { 
         // display response  
      Log.d("Response", response.toString()); 
     } 
    }, 
    new Response.ErrorListener() 
    { 
     @Override 
     public void onErrorResponse(VolleyError error) {    
      Log.d("Error.Response", response); 
     } 
    } 
); 

// add it to the RequestQueue 
queue.add(getRequest); 

Il mio punto qui è come ottenere questo codice tutte le richieste di un'altra classe e proprio esempio la classe e chiamare il makeRequest. Ho già provato questo, ma fallisce. Non so se è una cosa in relazione con il contesto, ma viene a mancare ...

ho fatto questo:

public void onClick(View v) { 
    try{ 

     Utils varRequest = new Utils(getApplicationContext()); 
     String url = "https://ajax.googleapis.com/ajax/services/search/web?v=1.0&q="; 

     varRequest.makeRequest(url); 
     mitexto.setText(varRequest.miError); 
    } 
    catch(Exception excepcion) { 
     System.out.println(excepcion.toString()); 

     } 

    } 

... e la classe Utils è:

public class Utils { 
    public Context contexto; 
    public String miError; 
    private RequestQueue queue ; 

    public Utils (Context contextoInstancia){ 
     contexto = contextoInstancia; 
     queue = Volley.newRequestQueue(contexto); 
    } 

    public void makeRequest(String url){ 

     JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() { 

      @Override 
      public void onResponse(JSONObject response) { 
       // TODO Auto-generated method stub 
       miError="Response => "+response.toString(); 
      } 
     }, new Response.ErrorListener() { 

      @Override 
      public void onErrorResponse(VolleyError error) { 
       // TODO Auto-generated method stub 
       miError="Response => "+error.networkResponse.toString(); 
      } 
     }); 

     queue.add(jsObjRequest); 
    } 
} 

Can qualcuno mi dice cosa sto facendo male, o come strutturare il codice?

Grazie in anticipo.

+0

asincrona è asincrono ... mitexto.setText (varRequest.miError); dovrebbe essere chiamato onResponse o onErrorResponse ... o classe che ha onClick dovrebbe implementare Response.Listener ... – Selvin

+1

hehehe, quindi invece 'Response.Listener ' dovrebbe usare 'CallBack '? dov'è la differenza? – Selvin

+2

Penso che la risposta di Rohit Patil in http://stackoverflow.com/questions/35628142/how-to-make-separate-class-for-volley-library-and-call-all-method-of-volley-from è la quello che vuoi – SajithK

risposta

47

in generale è buona norma separare questo genere di cose, in modo da siete sulla strada giusta, considerare la possibilità di una classe singelton che gestisce le vostre richieste - questo è un molto generale modello, ma dovrebbe ottenere la vostra struttura in corso:

creare una classe Singleton, che si instatiate quando sei applicazione viene in su:

public class NetworkManager 
{ 
    private static final String TAG = "NetworkManager"; 
    private static NetworkManager instance = null; 

    private static final String prefixURL = "http://some/url/prefix/"; 

    //for Volley API 
    public RequestQueue requestQueue; 

    private NetworkManager(Context context) 
    { 
     requestQueue = Volley.newRequestQueue(context.getApplicationContext()); 
     //other stuf if you need 
    } 

    public static synchronized NetworkManager getInstance(Context context) 
    { 
     if (null == instance) 
      instance = new NetworkManager(context); 
     return instance; 
    } 

    //this is so you don't need to pass context each time 
    public static synchronized NetworkManager getInstance() 
    { 
     if (null == instance) 
     { 
      throw new IllegalStateException(NetworkManager.class.getSimpleName() + 
        " is not initialized, call getInstance(...) first"); 
     } 
     return instance; 
    } 

    public void somePostRequestReturningString(Object param1, final SomeCustomListener<String> listener) 
    { 

     String url = prefixURL + "this/request/suffix"; 

     Map<String, Object> jsonParams = new HashMap<>(); 
     jsonParams.put("param1", param1); 

     JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST, url, new JSONObject(jsonParams), 
       new Response.Listener<JSONObject>() 
       { 
        @Override 
        public void onResponse(JSONObject response) 
        { 
         Log.d(TAG + ": ", "somePostRequest Response : " + response.toString()); 
         if(null != response.toString()) 
          listener.getResult(response.toString()); 
        } 
       }, 
       new Response.ErrorListener() 
       { 
        @Override 
        public void onErrorResponse(VolleyError error) 
        { 
         if (null != error.networkResponse) 
         { 
          Log.d(TAG + ": ", "Error Response code: " + error.networkResponse.statusCode); 
          listener.getResult(false); 
         } 
        } 
       }); 

     requestQueue.add(request); 
    } 
} 

quando l'applicazione viene in su:

public class MyApplication extends Application 
{ 
    //... 

    @Override 
    public void onCreate() 
    { 
     super.onCreate(); 
     NetworkManager.getInstance(this); 
    } 

//... 

} 

una semplice interfaccia listener per il callback (file separato farebbe bene):

public interface SomeCustomListener<T> 
{ 
    public void getResult(T object); 
} 

e, infine, da dove vuoi, il contesto è già in là, basta chiamare:

public class BlaBla 
{ 
    //..... 

     public void someMethod() 
     { 
      NetworkManager.getInstance().somePostRequestReturningString(someObject, new SomeCustomListener<String>() 
      { 
       @Override 
       public void getResult(String result) 
       { 
        if (!result.isEmpty()) 
        { 
        //do what you need with the result... 
        } 
       } 
      }); 
     } 
} 

è possibile utilizzare qualsiasi oggetto con l'ascoltatore, a seconda di ciò che è necessario ricevere, questo funziona anche per le richieste GET con alcune modifiche minori (vedere this SO thread for more about GET) e si può chiamare da qualsiasi luogo (onClicks, ecc.), Basta ricordare hanno bisogno di corrispondere tra m etodi.

Spero che questo aiuti e non troppo tardi!

+0

Come viene creato il 'customlistener'? – Sauron

+0

È un'interfaccia java di base che ti aiuta a trasferire un oggetto, a crearlo in un file separato (puoi copiarlo incollandolo da qui, che in realtà è tutto lì, potrebbe voler cambiare il nome), importarlo e quando dichiararlo come oggetto anonimo (passando in modo implicito la classe di interfaccia con 'new customListener ...' quando si chiama il metodo di richiesta desiderato), tutto ciò che resta da fare è sovrascriverlo e usare il suo valore di ritorno per continuare a funzionare. – TommySM

+0

@TommySM come posso ottenere le intestazioni di risposta usando il codice sopra? – user3197818

2

Io uso una soluzione semplice per questo. Crea ascoltatori (poiché sono interfaccia, non possono essere istanziati direttamente ma possono essere istanziati come classi anonime che implementano l'interfaccia) all'interno dell'attività o frammento. Passa queste istanze come parametri alla richiesta. (StringRequest, JsonObjectRequest o ImageRequest).

public class MainActivity extends Activity { 

private static final String URI_WEATHER = "http://marsweather.ingenology.com/v1/latest/"; 

private Listener<JSONObject> listenerResponse = new Listener<JSONObject>() { 

    @Override 
    public void onResponse(JSONObject response) { 
     Toast.makeText(MainActivity.this, "Resonse " + response.toString(), Toast.LENGTH_LONG).show(); 
    } 
}; 

private ErrorListener listenerError = new ErrorListener() { 

    @Override 
    public void onErrorResponse(VolleyError error) { 
     Toast.makeText(MainActivity.this, "Error " + error, Toast.LENGTH_LONG).show(); 

    } 
}; 

}

Successivamente, creare una classe che ha richiesta e passare questo ascoltatori di questo metodo di richiesta di classe, questo è tutto. Non spiego questa parte è come creare un oggetto di richiesta in qualsiasi tutorial. Ma puoi personalizzare questa classe come desideri. È possibile creare singleton RequestQueue per verificare la priorità o impostare i parametri del corpo http del corpo su questi metodi come parametri di misura.

public class NetworkManagerWeather { 

public static void getWeatherData(int method, Context context, String url, 
     Listener<JSONObject> listenerResponse, ErrorListener listenerError) { 
    JsonObjectRequest requestWeather = new JsonObjectRequest(Method.GET, url, null, listenerResponse, 
      listenerError); 
    Volley.newRequestQueue(context).add(requestWeather); 
} 

}

Infine richiamare questo metodo da MainActivity per instatnce

NetworkManagerWeather.getWeatherData(Method.GET, this, URI_WEATHER, listenerResponse, listenerError); 
Problemi correlati