Данные загружаются с сервера, но не добавляются в список - PullRequest
1 голос
/ 01 апреля 2019

У меня следующая ситуация: моя программа загружает данные с сервера и после добавляет их в ArrayList.

static List<Film> generateFilms(){
        Log.i(Tag, "In generate films");
        List <Film> films = new ArrayList<>();
        String BaseUrl = "http://www.omdbapi.com/";
        Retrofit.Builder builder = new Retrofit.Builder().baseUrl(BaseUrl)
                .addConverterFactory(GsonConverterFactory.create());
        OkHttpClient.Builder httpClient = new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .writeTimeout(10, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS);
        httpClient.addInterceptor(chain -> {
            Request original =  chain.request();
            Request.Builder requestBuilder = original.newBuilder()
                    .header("Authorization", "auth-value");
            Request request = requestBuilder.build();
            return chain.proceed(request);
        });
        Retrofit retrofit = builder.build();
        APIService apiService  = retrofit.create(APIService.class);
        final Call<Film> filmsCall = apiService.getFilms();
        filmsCall.enqueue(new Callback<Film>() {
            @Override
            public void onResponse(@NonNull Call<Film> call, @NonNull Response<Film> response) {
                if (response.isSuccessful()){
                    Film film = response.body();
                    films.add(film);
                    Log.i(Tag, "Response: "+Objects.requireNonNull(response.body()).getTitle());
                }
                else {
                    Log.i(Tag, "Response code: "+response.code());
                }
            }

            @Override
            public void onFailure(@NonNull Call<Film> call, @NonNull Throwable t) {
                Log.i(getClass().getSimpleName(), "Error: "+t);
            }
        });

        Log.i(Tag, "Size = "+films.size());
        return films;
    }

Но он делает это странным образом: сначала он возвращает массив, а затем получает данные (как я вижу из журналов). Вот логи:

2019-04-01 22:00:06.766 4974-4974/asus.example.com.exercise5 I/DataUtil: In generate films
2019-04-01 22:00:06.889 4974-4974/asus.example.com.exercise5 I/DataUtil: Size = 0
2019-04-01 22:00:07.367 4974-4974/asus.example.com.exercise5 I/DataUtil: Response: Batman

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

1 Ответ

0 голосов
/ 01 апреля 2019

Call<T>.enqueu() действует асинхронно, поэтому вы не можете вернуть данные из самого метода generateFilms, а только выполнить все необходимые действия в onResponse или создать собственный обратный вызов.

Пример:

interface OnLoaded {
  void onLoaded(Film film);
}

void generateFilms(OnLoaded callback) {
  ...
 filmsCall.enqueue(new Callback<Film>() {
            @Override
            public void onResponse(@NonNull Call<Film> call, @NonNull Response<Film> response) {
                if (response.isSuccessful()){
                    Film film = response.body();
                    mFilms.add(film);
                    Log.i(Tag, "Response: "+Objects.requireNonNull(response.body()).getTitle());

                    callback.onLoaded(film);
                }
                else {
                    Log.i(Tag, "Response code: "+response.code());
                }
            }

И используйте это:

private List<Film> mFilms = new ArrayList<Film>();  // class-level field

generateFilms(new OnLoaded() {
  @Override
  public void onLoaded(Film film) {
    mFilms.add(film);
    // do actions with film or mFilms if you need
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...