Sunday, July 24, 2016

Why async methods call sooner in Retrofit 2?

Leave a Comment

As you can see in the code below, I've call the getPostByPageId() method to get data from server and then check if the data was returned back, I do other jobs.

 private void recyclerViewJobs() {     getPostByPageId();     if (pageDtoList.size() > 0) {         emptyText.setVisibility(View.GONE);         recyclerView.setVisibility(View.VISIBLE);         PagesAdapter adapter = new PagesAdapter(pageDtoList, context);         recyclerView.setAdapter(adapter);         recyclerView.setLayoutManager(new LinearLayoutManager(context));     } else {         emptyText.setVisibility(View.VISIBLE);         recyclerView.setVisibility(View.GONE);     }   } 

.....

private void getPostByPageId() {      IPageEndPoint pageEndPoint = ServiceGenerator.createService(IPageEndPoint.class);     Call<List<PageDto>> call = pageEndPoint.getPostByPageId(profileId);     call.enqueue(new retrofit2.Callback<List<PageDto>>() {         @Override         public void onResponse(Call<List<PageDto>> call, Response<List<PageDto>> response) {             if (response.isSuccessful()) {                 pageDtoList = response.body();             } else {                 log.toast("response is not successful for getPostByPageId");             }         }          @Override         public void onFailure(Call<List<PageDto>> call, Throwable t) {             log.toast("getPostByPageId onFailure");         }     }); } 

I don't know why in the recyclerViewJobs() method, the if condition work first?

maybe I could not explain my issue very well but my big problem is to know when I want to get some data from REST and then use this data to another REST service, how can I do this job because enqueue in retrofit works asynchronous and do not wait for first method, because of that it is beginning the second method in another thread and because my data was not gotten from first method yet, my program was crashed and I didn't get the answer. That is my problem.....

Cheers

3 Answers

Answers 1

That's because retrofit's enqueue method is not a blocking method. which means the Thread calling it won't wait for it to finish its job. Like @Amir said, If you have other things to do after calling getPostByPageId(), you should put them after retrofit's callback:

    private void recyclerViewJobs() {         getPostByPageId();     }     private void getPostByPageId() {          IPageEndPoint pageEndPoint = ServiceGenerator.createService(IPageEndPoint.class);         Call<List<PageDto>> call = pageEndPoint.getPostByPageId(profileId);         call.enqueue(new retrofit2.Callback<List<PageDto>>() {             @Override             public void onResponse(Call<List<PageDto>> call, Response<List<PageDto>> response) {                 if (response.isSuccessful()) {                     pageDtoList = response.body();                     if (pageDtoList.size() > 0) {                         emptyText.setVisibility(View.GONE);                         recyclerView.setVisibility(View.VISIBLE);                         PagesAdapter adapter = new PagesAdapter(pageDtoList, context);                         recyclerView.setAdapter(adapter);                         recyclerView.setLayoutManager(new LinearLayoutManager(context));                     } else {                         emptyText.setVisibility(View.VISIBLE);                         recyclerView.setVisibility(View.GONE);                     }                 } else {                     log.toast("response is not successful for getPostByPageId");                 }             }              @Override             public void onFailure(Call<List<PageDto>> call, Throwable t) {                 log.toast("getPostByPageId onFailure");             }         });     } 

Answers 2

Your async call run first But your if-condition always goes false because if-condition not behave as you expected! As soon as your async request sent it goes to check if-condition and because your list is empty (your response from server is not fetch yet) it always return false.

If you want to call next operation just after your WebService response was successful you can do it with following code:

public void onResponse(Call<List<PageDto>> call, Response<List<PageDto>> response) {      if (response.body().YOUR_LIST.size() > 0) {         emptyText.setVisibility(View.GONE);         recyclerView.setVisibility(View.VISIBLE);         PagesAdapter adapter = new PagesAdapter(pageDtoList, context);         recyclerView.setAdapter(adapter);         recyclerView.setLayoutManager(new LinearLayoutManager(context));          //CALL_YOUR_NEXT webservice here     } else {         emptyText.setVisibility(View.VISIBLE);         recyclerView.setVisibility(View.GONE);     } } 

In your processResponse do your job. But one thing you should consider is that response.isSuccessful() return true most of time and it doesn't mean your responseBody contains data. according to document:

isSuccessful() Returns true if code() is in the range [200..300).

So the better way is to check that your response list contains data or not.

But as a better way (a bit difficult if you are beginner) is using RxJava/RxAndroid. you can process your call just one after other with flatMap.

Answers 3

What is an asynchronous task? Not only for retrofit but the answer is same for all, when you use asynchronous task to write some code, it seems you allow that code to run asynchronously, that is, any time it wants to run and that too in background without disturbing any other tasks and not giving any kind of effect on main UI thread. So asynchronous task clearly defines itself as a task running in background and the code written above or below is never affected by it. So in your case it asynchronous task might not have completed or may be it is possible that it might not had started also but it does not disturb your if condition. https://developer.android.com/reference/android/os/AsyncTask.html

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment