I have async call to server with this structure:
AuthAPI authAPI = retrofitService.getRetrofit().create(AuthAPI.class);
authAPI.registerUser(requestBody)
.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(@NonNull Call<ResponseBody> call,
@NonNull Response<ResponseBody> response) {
// Response processing.
}
@Override
public void onFailure(@NonNull Call<ResponseBody> call,
@NonNull Throwable t) {
// Failure processing.
}
});
This code is executed inside onClick() method of a button. After this code a new Fragment is replacing the current, but when this code executes due to .enqueue() is async the async part is not finished yet, so application is crashing. So, I need to wait until async code is executed and then show new fragment.
I could use execute() method instead of enqueue() method, but if I understand it right, until execute() method is finished the whole UI thread will be frozen and ProgressBar animation will not run. That is also bad for me.
So, what I am asking is, how could I wait for server response to be processed and dont lock my UI-thread so ProgressBar was spinning?
>Solution :
Yes, you should show some Progressbar before starting, then hide it in the onResponse, and after that, you can show your fragment, here is some code:
progressBar.setVisibility(View.VISIBLE);
authAPI.registerUser(requestBody).enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(@NonNull Call<ResponseBody> call,
@NonNull Response<ResponseBody> response) {
// Response processing.
runOnUiThread(new Runnable() {
@Override
public void run() {
progressBar.setVisibility(View.GONE); // hide progress bar when response is received
// Replace the current fragment with the new fragment here
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
NewFragment newFragment = new NewFragment();
fragmentTransaction.replace(R.id.fragment_container, newFragment);
fragmentTransaction.commit();
}
});
}
@Override
public void onFailure(@NonNull Call<ResponseBody> call,
@NonNull Throwable t) {
// Failure processing.
runOnUiThread(new Runnable() {
@Override
public void run() {
progressBar.setVisibility(View.GONE); // hide progress bar when response fails
}
});
}
});
The reason for using runOnUiThread is to ensure the View Updates and fragment transaction will happen on the main UI thread and not on the background thread that the enqueue operation works on, so it doesn’t raise an exception!