2015-12-14 33 views
7

Dla mojej aplikacji muszę skontaktować się z naszym API z naszego serwera, który zwraca niektóre JSON.Android: uzyskaj wynik z oddzwonienia (sieć KOUSH ION)

Podczas pobierania JSON powinien wyświetlać pasek postępu.

Pomyślałem powinienem używać Androida AsyncTask do obsługi GUI podczas wykonywania operacji sieciowych, więc pisał w moim 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); 

    } 

} 

Zasadniczo onPreExecute pokazuje spinner ładunku, doInBackGround pobiera niektóre JSON, i onPostExecute zatrzymuje spinner.

Pytanie brzmi, w downloadUtility.getId(id) muszę albo:

  1. otworzyć nową zamiaru jeśli pobieranie udało.
  2. Pozostań na tym samym działaniu i wyświetl komunikat o błędzie, jeśli pobieranie nie powiodło się.

Kod dla 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; 

} 

Jak widać, jestem powrocie przyszłego obiektu. Skąd mam wiedzieć z przyszłego obiektu, czy onCompleted (void) albo powiodło się, czy nie, więc mogę obsłużyć wynik (sukces: otwórz nowe intencje, nieudane: toast) w asynktasie?

Odpowiedz

3

Nie sądzę, że potrzebujesz AsyncTask do pracy w sieci, ponieważ twoja biblioteka jonowa używa wewnętrznie asynctask. można zrobić, jak to

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; 

dać mi znać, jeśli jakiś problem.

+0

Czy to nie oznacza, że ​​napiszesz kod pobierania w klasie aktywności? Powodem, dla którego stworzyłem klasę DownloadUtility, jest pozbycie się całego faktu, aby umieścić kod pobierania w działaniu i umieścić go w klasie, do której należy. –

+1

Tak, stwórz oddzielną klasę iw funkcji dodaj ten kod, aby można go było oddzielić – Rahul

+0

Gdybym tworzył osobną klasę, nie byłbym w stanie wywołać mLoadingSpinner, ponieważ klasa nie jest działaniem. Mogłabym przekazać loadspinnera do konstruktora obiektu downloadUtility, ale nie byłby to najlepszy sposób. (Kiedyś próbowałem tego). Ponadto, aby otworzyć nowe intencje z braku aktywności, musiałbym użyć FLAG, aby otworzyć nową działalność z normalnej klasy .. co nie jest miłym kodem –

6

Tutaj uruchamiasz jeden asynktask wewnątrz innego asyctask, nie jest to właściwy sposób, w jaki możesz wywołać metodę getId bezpośrednio w swojej aktywności, nie będzie potrzebny kolejny asynktask, ponieważ poniższy kod to samo asynktak.

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! 
        } 
       } 

      } 
     }); 

// Dodaj nowy odpowiedź

Jeśli chcesz, aby oddzielić cały kod do pobrania ze swojej działalności, a następnie można utworzyć niestandardową oddzwonienia w swojej klasie pobrania Utility. Będzie działać jak komunikator między działaniem a klasą Pobierz. Po prostu podam sposób na wykonanie tego zadania poniżej.

DownloadUtility klasy szwy wyglądają jak poniżej

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); 
        } 
       } 
      }); 
} 

}

wykonać połączenie na swojej działalności

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

Czy to nie znaczy że napiszesz kod pobierania w klasie aktywności? Powodem, dla którego stworzyłem klasę DownloadUtility, jest pozbycie się całego faktu, aby umieścić kod pobierania w działaniu i umieścić go w klasie, do której należy. –

+0

Wprowadziłem kilka zmian w odpowiedzi, zgodnie z Twoim wymaganiem, mam nadzieję, że to ci pomoże. –

+0

W powyższym kodzie nie chcesz przekazywać mLoadingSpinnerObject, możesz uruchomić go w samej aktywności, możesz ją uruchomić przed wywołaniem tej funkcji, a on onComplete możesz zatrzymać. –

0

Moim zdaniem najczystszym rozwiązaniem jest stworzenie usługi, która obsługuje brudną logikę pobierania i zwraca przyszłość niestandardowej klasy odpowiedzi, która zawiera informacje o sukcesie i obiekt 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

Nie testowałem kodu, mam nadzieję, że nie ma wielkich pomyłek :) – ronkot