How to achieve showing a progress bar on each Retrofit 2.0
API call without having to make a progress bar in each activity, showing it and dismissing. Progress bar should show whenever an API is hit and it should dismiss when we get a response on onResponse
or onFailure
is called.
I tried this :
ProgressDialog mProgressDialog = new ProgressDialog(this);
mProgressDialog.setIndeterminate(true);
mProgressDialog.setMessage("Loading...");
mProgressDialog.show();
retrofitService.login(new SignInRequest(email, password),
new Callback<SignInResponse>() {
@Override
public void onResponse(Call<SignInResponse> call, Response<SignInResponse> response) {
if (mProgressDialog.isShowing())
mProgressDialog.dismiss();
}
@Override
public void onFailure(Call<SignInResponse> call, Throwable t) {
if (mProgressDialog.isShowing())
mProgressDialog.dismiss();
}
});
But this code will have to copy pasted everywhere whenever I make an API call. I don;t want duplicate code.
Shameless Promotion
I've created RxLoading library for that, it can do this and much more,
you can just do something like this:
networkCall().compose(RxLoading.<>create(loadingLayout)).subscribe(...);
it consists out of 2 classes, a custom view (loadingLayout) and RxLoading which is a transformer that glue it all together, you can choose to work with both or either of them.
If you want one progress bar to rule them all, you have several options to achieve it depending on the structure of your app:
RxLoading also supports empty and error states (with built-in retry mechanism, so make sure to check this options as well)
you can find out more on the GitHub page.
A base class for your callbacks can be handy.
class BaseCallBack implements CallBacks<T>{
@Override
public void onResponse(Call<T> call, Response<T> response) {
if (mProgressDialog.isShowing())
mProgressDialog.dismiss();
}
@Override
public void onFailure(Call<SignInResponse> call, Throwable t) {
if (mProgressDialog.isShowing())
mProgressDialog.dismiss();
}
}
When you send a request:
retrofitService.login(new SignInRequest(email, password), new MyCallback<SignInResponse>() {
@Override
public void onResponse(Call<SignInResponse> call, Response<SignInResponse> response) {
super.onResponse(call, response);
//do more on response
}
@Override
public void onFailure(Call<SignInResponse> call, Throwable t) {
super.onFailure(call, t);
/* Do more on failure. For example: give a reason why the
request failed*/
}
});
Edit 2019 - using the RXjava adapter:
getUsers()
.subscribeOn(AndroidSchedulers.io()) //run request in the background and deliver response to the main thread aka UI thread
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe(() -> showLoading())
.doOnTerminate(() -> hideLoading())
.subscribe(data -> {
//request is successful
}, error -> {
//show error
});
As suggested by @Sourabh, I ended up using a Base activity and calling simple method during each API call. In BaseActivity
,
public void showDialog() {
if(mProgressDialog != null && !mProgressDialog.isShowing())
mProgressDialog.show();
}
public void hideDialog() {
if(mProgressDialog != null && mProgressDialog.isShowing())
mProgressDialog.dismiss();
}
In your child activity, you can directly call showDialog()
and hideDialog()
to show and dismiss dialog.
Based on the answers of Shubham and peter, I wrote a class like this:
class CustomCallBack<T> implements Callback<T> {
private ProgressDialog mProgressDialog;
Context context;
CustomCallBack(Context context) {
this.context = context;
mProgressDialog = new ProgressDialog(context);
((Activity) context).getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
mProgressDialog.setIndeterminate(true);
mProgressDialog.setMessage("Loading...");
mProgressDialog.setCanceledOnTouchOutside(false);
mProgressDialog.show();
}
@Override
public void onResponse(Call<T> call, Response<T> response) {
if (mProgressDialog.isShowing()) {
mProgressDialog.dismiss();
((Activity) context).getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
}
}
@Override
public void onFailure(Call<T> call, Throwable t) {
if (mProgressDialog.isShowing()) {
mProgressDialog.dismiss();
((Activity) context).getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
}
}
}
I hope it will help you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With