Отслеживание в asynctask ответа сервера, тайм-аута соединения. Взаимодействие с UI

Рейтинг: 0Ответов: 1Опубликовано: 24.03.2015

В приложении через AsyncTask забирается JSON с сервера (скрипт php).

Как прервать AsyncTask в случаях:

  1. Ответ сервера не 200 (перегружен, недоступен и т.п.).

  2. Таймаут ответа сервера превышает 5сек boolean timeResponse;.

  3. Отсутствует и мобильное интернет-соединение, и wi-fi (значка нет совсем).

И уже соответственно в UI выполнять действия в зависимости от ситуации?

Собственный класс AsyncTask:

public class GetDataTask extends AsyncTask<ApiGetJsonData, String, JSONArray> {

    @Override
    protected JSONArray doInBackground(ApiGetJsonData... params) {
        return params[0].GetJsonData();
    }

    @Override
    protected void onPostExecute(JSONArray jsonArray){
        // ... обрабатываем полученный jsonArray
    }
}

ApiGetJsonData:

public class ApiGetJsonData extends MainActivity {

    private String url;             // Путь к скриптам
    int status;                     // Статус ответа сервера
    int timeOut = 5000;             // Задержка ответа сервера
    boolean timeResponse;           // Ответ сервера по таймауту
    JSONArray jsonArray = null;     // Массив данных из ответа сервера
    HttpEntity httpEntity = null;   // Ответ сервера

// Конструктор для url
public ApiGetJsonData(String region){
    this.url = "http://../srcipt.php?region=" + region;
}

public JSONArray GetJsonData(){

    try {
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpGet httpGet = new HttpGet(url);
        HttpResponse httpResponse = httpClient.execute(httpGet);
        this.status = httpResponse.getStatusLine().getStatusCode();
        this.timeResponse = InetAddress.getByName(url).isReachable(timeOut);

        if (!timeResponse) {
             // .. ОТВЕТ СЕРВЕРА ДОЛЬШЕ 5 СЕКУНД
        }

        if (status == 200){             // Если нормальный ответ сервера (код 200)

            httpEntity = httpResponse.getEntity();
            String entityResponse = EntityUtils.toString(httpEntity);
            jsonArray = new JSONArray(entityResponse);
            Log.e("Данные с сервера (JSON): ", entityResponse);

        } else if (status == 503) {     // Если сервер перегружен/отключен
            // ... ЧТО-ТО ВИДИМО НАПИСАТЬ ТУТ
        } else {                        // Если пришел другой ответ сервера
             // ... И ТУТ ...
        }

    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (JSONException e) {
        e.printStackTrace();
    }
    Log.e("Ответ сервера: ", "status");

    return jsonArray;

}

Вызываю AsyncTask так:

new GetDataTask().execute(new ApiGetJsonData(region));

Также хотелось бы услышать ответы тех, кто применял уже подобное в своих проектах:

  1. Какие еще ответы сервера следует обрабатывать?

  2. Бывает ли ситуация, когда соединение с интернетом отсутствует (нет сети, совсем нет, в подвале на глубине 100 метров). Как в этом случае приложению избежать краша?

Ответы

▲ 1

Передавать в AsyncTask экземпляр Activity как параметр - это извращение. Прям-таки БДСМ. Перенесите метод GetJsonData вовнутрь AsyncTask, и все ваши проблемы решатся. Все ваши проблемы из-за того, что вы не можете получить доступ к объекту AsyncTask из метода GetJsonData.

И еще:

  1. Методы должны называться с маленькой буквы (GetJsonData).
  2. Так делать ни в коем случае, ни при каких обстоятельствах нельзя: new ApiGetJsonData(region). Нельзя самому вызывать конструктор Активити. Это должна делать только система!
  3. Стоит обрабатывать одинаково все ответы от сервера, кроме 200.
  4. Естественно, бывает ситуация, когда нет доступа в интернет. Избежать краша, как и в любом другом случае поможет try{...}catch(). Еще можно системными методами проверить предварительно подключение. Тык.