Получить статус погоды нескольких мест внутри для петли Android

1

Я разрабатываю приложение для погоды, для которого я использую API Dark Sky, в котором я хочу узнать состояние погоды для ряда мест, которые я сохранил в ArrayList<LatLng>.

Я использую OKHttp для анализа данных JSON из API, поэтому я попытался зациклить весь процесс извлечения внутри цикла for, но он не дает желаемого результата.

private void beginTask(ArrayList<LatLng> arrayLis) { 
    //arraylis contains list of locations(LatLng)
    m = 0;
    startTask = true;

    for (int i = 0;i<arrayLis.size();i++) {
        double latitude = ((LatLng)arrayLis.get(i)).latitude;
        double longitude = ((LatLng)arrayLis.get(i)).longitude;
        String url = "https://api.darksky.net/forecast/APIKEY/"
                +latitude+","+longitude+"?units=si";
        LatLng mylatlng = new LatLng(latitude,longitude);
        startProcess(url,mylatlng);

        Log.i("GGGTT",""+latitude+", "+longitude);
    }
}

private void startProcess(String myurl, final LatLng myLatlng){
    OkHttpClient httpClient = new OkHttpClient();
    Request request = new Request.Builder()
            .url(myurl)
            .build();

    Call call  = httpClient.newCall(request);
    call.enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            String data = response.body().string();
            Log.i("DATASS",data);
            if (response.isSuccessful()){
                try {
                    getCurrentDetails(data,myLatlng);
                } catch (JSONException e){
                    e.printStackTrace();
                }
            }
        }
    });
}

private void getCurrentDetails(String data,LatLng myLatlng) throws JSONException{
    JSONObject main = new JSONObject(data);
    double la = main.getDouble("latitude");
    double lon = main.getDouble("longitude");
    JSONObject currently = main.getJSONObject("currently");
    String summary = currently.getString("summary");
    double temperature = currently.getDouble("temperature");
    String icon = currently.getString("icon");

    LatLng latLngo = new LatLng(la,lon);
    ter.add(latLngo);
    weatherInfo.add(icon);

    // Output here is not in the same order that I have passed 

    Log.i("LETSCHECK",""+la+", "+lon +icon);
}

Я передаю значения как:

  1. 19.21111,73.07729
  2. 19.20238,73.06582
  3. 19.19383,73.05362
  4. 19.18848,73.04221

Но вывод не в том же порядке внутри метода getCurrentDetails

  1. 19.19383,73.05362
  2. 19.20238,73.06582
  3. 19.18848,73.04221
  4. 19.21111,73.07729

Я думаю, что метод не ждет до завершения предыдущего цикла.

Существуют ли какие-либо решения для получения статуса погоды всех мест, хранящихся в ArrayList без изменения его порядка?

РЕДАКТИРОВАТЬ

Привет! Я прошел этот метод для извлечения данных по порядку, и он работает нормально, спасибо, но еще одна проблема заключается в том, что я ожидал показать данные 4 раза, поскольку в ArrayList есть четыре значения LatLng, и он работает нормально, но когда я пытаюсь читать извлекаемые данные, которые я сохранил в другом массиве, он показывает только 2 элемента, а не 4.

private void getCurrentDetails(String data,LatLng myLatlng) throws JSONException{

    JSONObject main = new JSONObject(data);
    double la = main.getDouble("latitude");
    double lon = main.getDouble("longitude");
    JSONObject currently = main.getJSONObject("currently");
    String summary = currently.getString("summary");
    double temperature = currently.getDouble("temperature");
    String icon = currently.getString("icon");

    //Log.i("LETSCHECK",""+la+", "+lon +icon+",k");

    loopi++;
    Log.i("LETSCHECK",""+loopi);
    if (loopi < arrayList.size()) {
        getItAgain();
    } else if (loopi == arrayList.size()){
        for (String l:weatherInfo){
            Log.i("LETSCHECK",l); 
            //expected 4 items to show but its showing only 2 items
        }
    }

    Log.i("LETSCHECK",""+la+", "+lon +icon);
    weatherInfo.add(icon); 
}

private void getItAgain() {
    double latitude = ((LatLng)arrayList.get(loopi)).latitude;
    double longitude = ((LatLng)arrayList.get(loopi)).longitude;
    String url = "https://api.darksky.net/forecast/74d8feeda5ecf5ee6667d034778b239d/"
            +latitude+","+longitude+"?units=si";
    LatLng mylatlng = new LatLng(latitude,longitude);
    startProcess(url,mylatlng);
}             
Теги:
location
okhttp
weather-api

3 ответа

0
Лучший ответ

Сетевые вызовы асинхронны, и это ожидаемое поведение, которое вы здесь имеете. Если вы хотите отсортировать их по мере их прохождения, вам может понадобиться механизм ожидания завершения сетевого вызова предыдущего, а затем повторный вызов следующего. Однако это может увеличить задержку ожидания ответа от сервера, поскольку вы не получаете несколько ответов от сервера одновременно.

Если вы хотите дождаться ответа, чтобы сохранить отсортированный способ, вам может потребоваться сделать следующее.

// Declare a global variable of the list of your locations. 
ArrayList<LatLng> arrayLis; 
int i = 0; 

// Just start the first task without the loop. 
double latitude = ((LatLng)arrayLis.get(i)).latitude;
double longitude = ((LatLng)arrayLis.get(i)).longitude;
String url = "https://api.darksky.net/forecast/APIKEY/"
        +latitude+","+longitude+"?units=si";
LatLng mylatlng = new LatLng(latitude,longitude);
startProcess(url,mylatlng);

Теперь в функции getCurrentDetails вам, возможно, придется сделать следующее.

private void getCurrentDetails(String data,LatLng myLatlng) throws JSONException{
    JSONObject main = new JSONObject(data);
    double la = main.getDouble("latitude");
    double lon = main.getDouble("longitude");
    JSONObject currently = main.getJSONObject("currently");
    String summary = currently.getString("summary");
    double temperature = currently.getDouble("temperature");
    String icon = currently.getString("icon");

    LatLng latLngo = new LatLng(la,lon);
    ter.add(latLngo);
    weatherInfo.add(icon);

    // Now initiate the next call
    i++;
    if(i < arrayLis.size()) getItAgain();

    Log.i("LETSCHECK",""+la+", "+lon +icon);
}

public void getItAgain() {
    // Just start the first task without the loop. 
    double latitude = ((LatLng)arrayLis.get(i)).latitude;
    double longitude = ((LatLng)arrayLis.get(i)).longitude;
    String url = "https://api.darksky.net/forecast/APIKEY/"
            +latitude+","+longitude+"?units=si";
    LatLng mylatlng = new LatLng(latitude,longitude);
    startProcess(url,mylatlng);
}

Обновить

Я не понимаю, почему он показывает 2 вместо 4 результатов. Тем не менее, я думаю, что вам нужно изменить код следующим образом.

private void getCurrentDetails(String data,LatLng myLatlng) throws JSONException {

    JSONObject main = new JSONObject(data);
    double la = main.getDouble("latitude");
    double lon = main.getDouble("longitude");
    JSONObject currently = main.getJSONObject("currently");
    String summary = currently.getString("summary");
    double temperature = currently.getDouble("temperature");
    String icon = currently.getString("icon");

    // Move this upto here
    weatherInfo.add(icon);

    loopi++;
    Log.i("LETSCHECK",""+loopi);
    if (loopi < arrayList.size()) {
        getItAgain();
    } else {
        for (String l:weatherInfo) {
            Log.i("LETSCHECK",l); 
            //expected 4 items to show but its showing only 2 items
        }
    }
}
  • 0
    привет Reaz спасибо за вашу помощь, дайте мне попробовать, и я дам вам знать
  • 0
    Должен ли я переместить весь этот код в класс IntentService, чтобы он не блокировал весь основной интерфейс
Показать ещё 5 комментариев
0

Это пример кода. После каждого успешного вызова удалите текущий элемент продолжения из массива и выполните другой запрос API.

private void startProcess(ArrayList<LatLong> elementList){
LatLong myLatlng = elementList.get(0);
OkHttpClient httpClient = new OkHttpClient();
Request request = new Request.Builder()
        .url(myurl)
        .build();
Call call  = httpClient.newCall(request);
call.enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {

    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {

        String data = response.body().string();
        Log.i("DATASS",data);
        if (response.isSuccessful()){
            try {
                getCurrentDetails(data,myLatlng);
                elementList.remove(0)
                startProcess(elementList)
            }catch (JSONException e){
                e.printStackTrace();
            }


        }
    }

});

}

  • 0
    привет, спасибо за размещение кода, я уже пробовал другое решение, и оно прекрасно работает.
0

Вы выполняете асинхронный код, и причина, по которой их обратные вызовы не возвращаются один за другим, логична, поскольку каждый HTTP-вызов занимает некоторое время, не связанное с остальными, поэтому ответ на ваш третий вызов может фактически быть получен до первого один.

Вы можете использовать RxJava (и его операторы) или улучшить текущий код. Для вашего startProcess передайте i из цикла for в качестве индекса и создайте массив вне нашей функции. Всякий раз, когда вы получаете ответ от сервера, вы можете сохранить его в i й позиции вашего массива. После каждого вызова вы можете проверить, все ли значения были получены (счетчиком или чем-то еще). Гораздо лучше перенести весь этот материал в его собственный класс, чтобы он содержал и тестировался.

Следует обратить внимание на то, как вы будете обрабатывать ошибки, потому что ваши звонки могут быть не приняты успешно.

  • 0
    Спасибо за вашу помощь, я дам вам знать, если это работает.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню