Faced the following situation: the method must load data from the server and add it to the ArrayList . Here is the code:

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

But for some reason, the array is returned first and only then the data is added to it. As I understand it, this is due to the fact that the data is received from the server asynchronously. How, then, to fix this problem?

  • one
    1) synchronous request (not applicable if the method is called in the UI thread). 2) the method returns nothing, and the event that should occur after receiving the data is called from the request callback - woesss

1 answer 1

My option for data acquisition and processing may be useful to you.

 private boolean sendHttpRequest(int city_id,String lang_id,String upd){ OkHttpClient client = new OkHttpClient(); RequestBody requestBody = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("city_id", String.valueOf(city_id)) .addFormDataPart("lang_id", lang_id) .addFormDataPart("upd", upd) .build(); final Request request = new Request.Builder() .url(http) .post(requestBody) .build(); client.newCall(request).enqueue(new Callback() { String myResponse; @Override public void onFailure(Call call, IOException e) { Log.d(TAG, e.toString()); // no need inside run() } @Override public void onResponse(Call call, Response response) throws IOException { myResponse = response.body().string(); //Log.d(TAG, myResponse); // no need inside run() if(!getErrorFromRequest(myResponse)){ getJsonHandler(myResponse); } // must be inside run() } }); return SharedPrefManager.getmInstance(getActivity()).getKey("key_some")!=null ? false : true; } 

separately made a method for error handling

 private boolean getErrorFromRequest(String myResponse) { // тут ваши правила обработки return false; } 

If we have data obtained without any problems, then we process

 private void getJsonHandler(String myResponse) { getWhatYouNeed(myResponse,"key","key_to_save"); } private void getWhatYouNeed(String response,String keygen, String key) { try { JSONObject obj = new JSONObject(response); JSONArray object = obj.getJSONArray(keygen); SharedPrefManager.getmInstance(getActivity()).setKey(String.valueOf(object),key); Log.d("IsSet"+keygen, String.valueOf(object)); } catch (JSONException e) { e.printStackTrace(); } }