I am making an android application with a lot a activities and Retrofit 2 requests and I want to know what are the best practices for the loading animations during a request ?
Actually, I use my loading animation like this :
public void getLogin() {
showDialog();
retrofitService.getLogin(new Callback<SignInResponse>() {
#Override
public void onResponse(Call<SignInResponse> call, Response<SignInResponse> response) {
hideDialog()
//My stuff
}
#Override
public void onFailure(Call<SignInResponse> call, Throwable t) {
hideDialog()
//My stuff again
}
});
}
public void showDialog() {
ProgressDialog mProgressDialog = new ProgressDialog(this); //Which is deprecated
mProgressDialog.setIndeterminate(true);
mProgressDialog.setMessage("Loading...");
if(mProgressDialog != null && !mProgressDialog.isShowing())
mProgressDialog.show();
}
public void hideDialog() {
if(mProgressDialog != null && mProgressDialog.isShowing())
mProgressDialog.dismiss();
}
I know that ProcessDialog is deprecated since API26 so if you have better ideas, I'll take them !
But it seems like I need to copy past every time this code when I do a requests and I wonder there is a better way to do that.
Thanks for your help :)
Related
if i call onclick="showLoader();" on my webview site,
i get this onclick error in my log
Android Studio log:
"Error calling method on NPObject."
anyone who knows something about this Dialog webview error?
I would be very grateful
Best Regards
Dialog:
public class ProgressDialogHelper {
private static ProgressDialog progress;
public static void dismissProgress() {
if (progress != null) {
progress.dismiss();
progress.cancel();
progress = null;
}
}
public static void showProgress(Context mContext) {
if (progress != null) {
return;
}
progress = new ProgressDialog(mContext);
progress.setView(View.inflate(mContext, R.layout.progress_bar_layout, null));
progress.setMessage(mContext.getResources().getString(R.string.loading));
progress.show();
}
}
Activity:
#JavascriptInterface
public void showLoader() {
ProgressDialogHelper.showProgress(mContext);
}
#JavascriptInterface
public void hideLoader() {
ProgressDialogHelper.dismissProgress();
}
This solution dont works for me:
#JavascriptInterface
public void showLoader() {
((MainActivity) mContext).runOnUiThread(new Runnable() {
#Override
public void run() {
ProgressDialogHelper.showProgress(mContext);
}
});
}
I'm not sure why you are getting this error, but ProgressDialog is deprecated since api 26.
https://developer.android.com/reference/android/app/ProgressDialog
My recommendation is to use ProgressBar embedded in your UI as the documentation says and if you need to block the UI use:
getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
Just make sure to clear the flag once the ProgressBar is hiding.
onChanged I am updating the UI and cancelling the progressDialog but each time I am rotating the screen the progress dialog shows up and ProgressDialog doesn't dismiss.
How to handle the progressdialog if the data is not changed?
final ProgressDialog pd;
pd=new ProgressDialog(mContext);
pd.setMessage(mContext.getString(R.string.updating));
pd.show();MutableLiveData<BillGetResponse> DisplayByIdLiveData=viewModelForBillDisplay.getBillGetResponseDisplayById(txnRequest);
if (display_by_id) {
DisplayByIdLiveData.observe(BillDisplayFragment.this, new Observer<BillGetResponse>() {
#Override
public void onChanged(#Nullable BillGetResponse billGetResponse) {
if (btnRecordDisableEnabled != null)
btnRecordDisableEnabled.enable();
pd.dismiss(); }
but everytime the onChanged is not trigerred and the progressdialog doesnot stop !!
You need other observer to handle the value of the boolean that indicates if you have to show the ProgressDialog or not. This is the code:
viewModel.getIsLoading().observe(this, new Observer<Boolean>() {
#Override
public void onChanged(#Nullable Boolean aBoolean) {
if(aBoolean){
pd.show();
}else{
pd.dismiss();
}
}
});
In your viewModel add getIsLoading method:
public LiveData<Boolean> getIsLoading(){
LiveData<Boolean> isLoading=yourRepository.getIsLoading();
return isLoading;
}
And in your repository add:
private final MutableLiveData<Boolean> isLoading=new MutableLiveData<>();
and set value to isLoading when start and finish the data upload.
I hope it helps you.
onChanged() not getting called is perfectly normal, it means there are no more changes in data.
I guess you want to show ProgressDialog while data is being fetched or loaded. You can do something like this
In onCreate() Check data is present or not before displaying, below in Pseudo code for displaying ProgressDialog
if (!hasData())
displayProgressDialog()
EDIT:
It seems you want to inform user that data has changed by means of showing ProgressDialog, You can achieve this by showing this for small moment and dismiss it after a while, Something like this in onChanged()
#Override
public void onChanged(#Nullable BillGetResponse billGetResponse) {
if (btnRecordDisableEnabled != null)
btnRecordDisableEnabled.enable();
displayProgressDialog(); //Show progress dialog here
new Handler().postDelayed(new Runnable(){
#Override
public void run() {
pd.dismiss();
}
},500);
}
I have a ListFragment which has an AsyncTask in it to write data to a remote store. I need to have a ProgressDialog show status while the data is being sent since this may take a considerable time depending on the number of files being stored remotely. I have done this successfully from an Activity, but I am having issues showing progress within the ListFragments AsyncTask.
This is complicated by the fact that I need to show updates within the doInBackground method of the task, since that is where the major of the work is being done. That said, the ProgressDialog is not showing up at all even in the non-UI bound onPreExecute() method. Looking at other posts for ProgressDialogs I am using passing getActivity() to the ProgressDialog. Also this mechanism is working with several other Activity classes I am using else where, just not here. I am probably just missing something obvious so any help is appreciated.
Here is a code example - forgive me if it does not compile or has a mistake - I had to remove boatloads of code to boil it down to the problem at hand:
public class MyFragment extends ListFragment {
private ProgressDialog mProgress;
private void hideProgress() {
if (mProgress != null) {
mProgress.dismiss();
mProgress = null;
}
}
private void showProgress(String message) {
if (mProgress != null) {
mProgress.dismiss();
mProgress = null;
}
mProgress = ProgressDialog.show(getActivity(), null, message, true, false);
}
protected void updateProgressMessage(String message) {
if (mProgress != null && mProgress.isShowing()) {
mProgress.setMessage(message);
}
}
public syncForms() {
new syncPendingFormsResultTask().execute();
}
private class syncTask extends AsyncTask<Object, String, Boolean> {
#Override
protected void onCancelled() {
hideProgress();
}
#Override
protected void onPreExecute() {
showProgress("Submitting Form...");
}
#Override
protected Boolean doInBackground(Object... params) {
onProgressUpdate("Uploading Form");
}
#Override
protected void onProgressUpdate(String... values) {
String message = values[0];
updateProgressMessage(message);
}
#Override
protected void onPostExecute(Boolean result) {
showProgress("Upload Complete...");
hideProgress();
}
}
}
}
The syncForms() is the method called to initiate the task.
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.
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.
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:
one Activity multiple fragments -> just put a loadingLayout in the main screen and tell it to hide the fragment layout when loading
multiple activities: create a base activity which all uses and inject a loadingLayout to all of you views
you can also make a special dialog or activity for the progress bar and use an interface for RxLoading to show and hide it.
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.
Example from tutorial:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
requestWindowFeature(Window.FEATURE_PROGRESS);
ArrayAdapter<Question> arrayAdapter =
new ArrayAdapter<Question>(this,
android.R.layout.simple_list_item_1,
android.R.id.text1,
new ArrayList<Question>());
setListAdapter(arrayAdapter);
setProgressBarIndeterminateVisibility(true);
setProgressBarVisibility(true);
}
Tutorial link:http://www.vogella.com/tutorials/Retrofit/article.html
i am downloading data from website using asynctask and
my code for async task is below
public class getSyncTaskInBackground extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... params) {
getSynchronizeTask();
return null;
}
#Override
protected void onPostExecute(Void result) {
if(progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
displaySynchronizetask();
super.onPostExecute(result);
}
#Override
protected void onPreExecute() {
progressDialog = ProgressDialog.show(synchronize.this, "Tasks are synchroning...", "Please wait...");
super.onPreExecute();
}
#Override
protected void onCancelled() {
super.onCancelled();
if(progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
}
this thread takes more time to complete task
so if i want to cancel this thread in between of process then i had write this code of back button pressed
or if progressbar is already dismiss then i want to close activity by calling finish();
my code for back button is as below
#Override
public void onBackPressed() {
syncThread.cancel(true); //syncThread is the object of getSyncTaskInBackground
if(progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
} else {
finish();
}
}
Now when i pressed back button then the progressdialog is not dismiss
is any mistake in mycode ? is any way to complete my need ?
please help me
Hi
You might want to call
setCancelable with true on your progressDialog instance :
http://developer.android.com/reference/android/app/Dialog.html#setCancelable(boolean)
If you want an event on the cancelation of your progressDialog
you can set an onCancelListener
http://developer.android.com/reference/android/app/Dialog.html#setOnCancelListener(android.content.DialogInterface.OnCancelListener)
hope this helps