2015-12-14 27 views
7

Per la mia app ho bisogno di contattare la nostra API dal nostro server che restituisce alcuni JSON.Android: ottenere risultato da callback (networking KOUSH ION)

Durante il download del JSON, dovrebbe visualizzare una barra di avanzamento.

ho pensato dovrei usare AsyncTask di Android per gestire l'interfaccia grafica, mentre facendo le operazioni di rete, così ho scritto il seguente nel mio Activity:

class DownloadManager extends AsyncTask<String, Void, Boolean> { 

    @Override 
    protected void onPreExecute() { 
     super.onPreExecute(); 
     mLoadingSpinner.setVisibility(View.VISIBLE); 
    } 

    @Override 
    protected Boolean doInBackground(String... params) { 
     String id = params[0]; 
     downloadUtility.getId(id); 

     return true; 
    } 

    @Override 
    protected void onPostExecute(Boolean result) { 
     super.onPostExecute(result); 

     mLoadingSpinner.setVisibility(View.INVISIBLE); 

    } 

} 

In sostanza, onPreExecute mostra il filatore di carico, il doInBackGround downloads alcuni JSON, e onPostExecute interrompe la selezione.

La domanda è, all'interno del downloadUtility.getId(id) ho bisogno di uno:

  1. Aprire un nuovo intento se il download è riuscito .
  2. Rimanere sulla stessa attività e visualizzare un messaggio di errore se il download non è riuscito.

Il codice per la getId:

public Future getId(final String id) { 
    // set url 
    String url = IPAddress.PRODUCTION + Variables.get_id+ id; 
    downloading = Ion.with(context) 
      .load("GET", url) 
      .asJsonObject() 
      .withResponse() 
      .setCallback(new FutureCallback<Response<JsonObject>>() { 
       @Override 
       public void onCompleted(Exception e, Response<JsonObject> response) { 
        //try catch here for null getHeaders 
        if (response != null) { 
         if (response.getHeaders().code() == 200) { 

          //SUCCESS !! Open new intent! 


         } else { 
          //FAIL!! Show TOAST! 
         } 
        } 

       } 
      }); 


    return downloading; 

} 

Come potete vedere, sto tornando un oggetto futuro. Come faccio a sapere dall'oggetto futuro se lo onCompleted (void) ha dato esito positivo o negativo, quindi posso gestire il risultato (successo: aprire nuovo intent, fail: toast) nel asynctask?

risposta

3

Non penso che sia necessario AsyncTask per il funzionamento in rete perché la libreria di ioni utilizza già internamente asynctask. si può fare in questo modo

mLoadingSpinner.setVisibility(View.VISIBLE); 
downloading = Ion.with(context) 
      .load("GET", url) 
      .asJsonObject() 
      .withResponse() 
      .setCallback(new FutureCallback<Response<JsonObject>>() { 
       @Override 
       public void onCompleted(Exception e, Response<JsonObject> response) { 
        //try catch here for null getHeaders 
        if (response != null) { 
         if (response.getHeaders().code() == 200) { 

          //SUCCESS !! Open new intent! 
          mLoadingSpinner.setVisibility(View.INVISIBLE); 
         } else { 
          mLoadingSpinner.setVisibility(View.INVISIBLE); 
         } 
        } 

       } 
      }); 
    return downloading; 

fatemi sapere se qualche problema.

+0

Ciò non significa che si scriverà codice di download all'interno di una classe di attività? Il motivo per cui ho creato una classe DownloadUtility è di eliminare l'intero fatto di inserire il codice di download all'interno di un'attività e inserirlo in una classe a cui appartiene. –

+1

Sì, crea una classe separata e in una funzione aggiungi questo codice in modo da renderlo separato – Rahul

+0

Se crei una classe separata, non potrei chiamare mLoadingSpinner poiché la classe non è un'attività. Potrei passare loadingspinner nel costruttore dell'oggetto downloadUtility, ma non sarebbe il modo migliore. (Una volta ho provato questo). Inoltre, per aprire un nuovo intent da una non attività, dovrei usare un FLAG per aprire una nuova attività da una classe normale .. che non è bello codice –

6

Qui si sta eseguendo un asynctask all'interno di un altro asyctask questo non è un modo corretto per chiamare il metodo getId direttamente nella propria attività, non sarà richiesto un altro asynctask perché il seguente codice è un asynctask.

downloading = Ion.with(context) 
     .load("GET", url) 
     .asJsonObject() 
     .withResponse() 
     .setCallback(new FutureCallback<Response<JsonObject>>() { 
      @Override 
      public void onCompleted(Exception e, Response<JsonObject> response) { 
       //try catch here for null getHeaders 
       if (response != null) { 
        if (response.getHeaders().code() == 200) { 

         //SUCCESS !! Open new intent! 


        } else { 
         //FAIL!! Show TOAST! 
        } 
       } 

      } 
     }); 

// Aggiungere nuova risposta

Se si vuole separare tutto il codice per il download dalla vostra attività quindi è possibile creare callBack personalizzato nella classe scaricare Utility. Funzionerà come un comunicatore tra l'attività e la classe di download. Dò solo un modo per fare questo compito su muggito.

DownloadUtility cuciture di classe sembrano muggito

public class DownloadUtility { 


//DO Your all other Stuff 

/** 
* Custom Callback 
*/ 
public interface customCallBack { 
    void onCompleted(Exception e, Response<JsonObject> response); 
} 


/** 
* Your getID code 
* 
* @param context 
* @param id 
* @param mLoadingSpinner 
* @param callBack 
*/ 
public static void getId(Activity context,final String id, Spinner mLoadingSpinner, final customCallBack callBack) { 
    // set url 
    mLoadingSpinner.setVisibility(View.VISIBLE); 
    String url = IPAddress.PRODUCTION + Variables.get_id + id; 
    downloading = Ion.with(context) 
      .load("GET", url) 
      .asJsonObject() 
      .withResponse() 
      .setCallback(new FutureCallback<Response<JsonObject>>() { 
       @Override 
       public void onCompleted(Exception e, Response<JsonObject> response) { 
        mLoadingSpinner.setVisibility(View.GONE); 
        if(callBack != null) 
        callBack.onCompleted(e,response); 
        } 
       } 
      }); 
} 

}

effettuare una chiamata sul tuo Attività

DownloadUtility.getId(this, "ID", spinnerObj, new DownloadUtility.customCallBack() { 
@Override 
public void onCompleted(Exception e, Response<JsonObject> response) { 
    if (response != null) { 
     if (response.getHeaders().code() == 200) { 
      //SUCCESS !! Open new intent! 
     } else { 
      //FAIL!! Show TOAST! 
     } 
} 

});

+0

Questo non significa che scriverai il codice di download all'interno di una classe di attività? Il motivo per cui ho creato una classe DownloadUtility è di eliminare l'intero fatto di inserire il codice di download all'interno di un'attività e inserirlo in una classe a cui appartiene. –

+0

Ho apportato alcune modifiche in risposta secondo le tue esigenze, spero che possa aiutarti. –

+0

Nel codice precedente non si desidera passare mLoadingSpinnerObject, è possibile avviarlo nell'attività stessa, è possibile avviarlo prima di chiamare tale funzione e onComplete è possibile interrompere. –

0

A mio parere, la soluzione più pulita è quella di creare un servizio che gestisca la logica di download sporca e restituisca un futuro della classe di risposta personalizzata, che contiene le informazioni di successo e l'oggetto json.

// in e.g JsonResponse.java 
public class JsonResponse() { 
    public boolean ok; 
    public JsonObject json; 
} 

// in Service.java 
public Future<JsonResponse> getId(final String id) { 
    final SimpleFuture<JsonResponse> jsonFuture = new SimpleFuture<>(); 

    String url = IPAddress.PRODUCTION + Variables.get_id + id; 
    Ion.with(context) 
    .load("GET", url) 
    .asJsonObject() 
    .withResponse() 
    .setCallback(new FutureCallback<Response<JsonObject>>() { 
     @Override 
     public void onCompleted(Exception e, Response<JsonObject> response) { 
      JsonResponse jsonResponse = new JsonResponse(); 
      if (response != null) { 
       if (response.getHeaders().code() != 200) { 
        jsonResponse.ok = false; 
       } else { 
        jsonResponse.ok = true; 
        jsonResponse.json = response.getResult(); 
       } 
      } 
      jsonFuture.setComplete(jsonResponse); 
     } 
    }); 

    return jsonFuture; 
} 


// in Activity.java 
private void loadUser(String userId) {  
    mLoadingSpinner.setVisibility(View.VISIBLE); 

    service.getId(userId) 
    .setCallback(new FutureCallback<JsonResponse>() { 

     // onCompleted is executed on ui thread 
     @Override 
     public void onCompleted(Exception e, JsonResponse jsonResponse) { 
      mLoadingSpinner.setVisibility(View.GONE); 
      if (jsonResponse.ok) { 
       // Show intent using info from jsonResponse.json 
      } else { 
       // Show error toast 
      } 
     } 
    }); 
} 
+0

Non ho provato il codice, spero che non ci siano grandi mistkases :) – ronkot