171

What is the best way to show a loading spinner while the app is waiting for a response from the server?

Can this be done programmatically? So that I don't have to add the load spinner in the xml file?

biniam
  • 8,099
  • 9
  • 49
  • 58
Jochem Gruter
  • 2,813
  • 5
  • 21
  • 43

5 Answers5

311

ProgressDialog is deprecated from Android Oreo. Use ProgressBar instead

ProgressDialog progress = new ProgressDialog(this);
progress.setTitle("Loading");
progress.setMessage("Wait while loading...");
progress.setCancelable(false); // disable dismiss by tapping outside of the dialog
progress.show();
// To dismiss the dialog
progress.dismiss();

OR

ProgressDialog.show(this, "Loading", "Wait while loading...");

Read more here.

By the way, Spinner has a different meaning in Android. (It's like the select dropdown in HTML)

vwvw
  • 372
  • 4
  • 16
Suraj Bajaj
  • 6,630
  • 5
  • 34
  • 49
  • 2
    From the Android Developer website: STYLE_SPINNER Creates a ProgressDialog with a circular, spinning progress bar. – Eric Engel Dec 26 '14 at 01:15
  • 36
    This works, but when I tested this, I could dismiss the dialog by touching the screen outside of it or pressing the *Back* button. I fixed this by adding a call to `progress.setCancelable(false);`. – Sam Jun 20 '15 at 22:28
  • 1
    Thanks for the bottom comment. I was going crazy because I was trying to get 'spinner' to work for an hour. – Can Poyrazoğlu Jun 08 '16 at 16:16
  • superb, now I can use progress dialog – Faisal May 12 '17 at 11:26
  • 12
    `ProgressDialog` was deprecated in Android O https://developer.android.com/reference/android/app/ProgressDialog.html – Ivan Semkin May 20 '17 at 10:53
  • Progress dialogs are bad UX in general. Avoid them. – WindRider May 21 '17 at 15:53
  • ProgressDialog is now deprecated and should be avoided. – NibbleBits Nov 17 '17 at 15:32
  • 1
    @IvanSemkin Any suggestions on alternatives to be used instead? – Babken Vardanyan Mar 28 '18 at 10:28
  • 1
    @BabkenVardanyan as written in documentation: _ProgressDialog is a modal dialog, which prevents the user from interacting with the app. Instead of using this class, you should use a progress indicator like ProgressBar, which can be embedded in your app's UI. Alternatively, you can use a notification to inform the user of the task's progress._ Sometimes I use also a SwipeRefreshLayout that shows a loading indicator and could be useful also to refresh in case of network failure. It can be activated/deactivated programmatically, but you need to insert it in layout xml. – leodev May 30 '18 at 14:06
  • @leodev Good points. However I am looking for a solution that doesn't clutter my layout xml, and notifications is a different thing altogether. – Babken Vardanyan May 30 '18 at 14:21
  • anything in android that was once easy and quick to implement has been deprecated as a general rule. if it makes life easy, it's been deprecated. – Adam R. Turner Oct 28 '19 at 00:53
29

ProgressDialog has become deprecated since API Level 26 https://developer.android.com/reference/android/app/ProgressDialog.html

I include a ProgressBar in my layout

   <ProgressBar
        android:layout_weight="1"
        android:id="@+id/progressBar_cyclic"
        android:visibility="gone"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:minHeight="40dp"
        android:minWidth="40dp" />

and change its visibility to .GONE | .VISIBLE depending on the use case.

    progressBar_cyclic.visibility = View.VISIBLE
Ilker Baltaci
  • 11,644
  • 6
  • 63
  • 79
  • Not sure, but does the progressBar run always in background(just hidden from the UI) after making it invisible? – Shambhu May 15 '18 at 06:43
  • @Shambhu if you set it to `View.GONE`, it doesn't render in UI at all and has no negative effect to performance. `View.INVISIBLE` is like making it transparent, but it's in UI thus worse for performance. – Micer Feb 03 '21 at 09:37
16

Use ProgressDialog

ProgressDialog.show(Context context, CharSequence title, CharSequence message);

enter image description here

However this is considered as an anti pattern today (2013): http://www.youtube.com/watch?v=pEGWcMTxs3I

DarkLeafyGreen
  • 69,338
  • 131
  • 383
  • 601
vasart
  • 6,692
  • 38
  • 39
  • 12
    @artworkadシ So what aspect of this is considered bad -- is the accepted answer an example of the same anti-pattern? And what is recommended to do instead? Linking to a offsite video about multiple UX issues does not really improve this answer. – LarsH Aug 20 '15 at 19:36
  • 3
    `ProgressDialog` was deprecated in Android O https://developer.android.com/reference/android/app/ProgressDialog.html – Ivan Semkin May 20 '17 at 10:53
11

Actually if you are waiting for response from a server it should be done programatically. You may create a progress dialog and dismiss it, but then again that is not "the android way".

Currently the recommended method is to use a DialogFragment :

public class MySpinnerDialog extends DialogFragment {

    public MySpinnerDialog() {
        // use empty constructors. If something is needed use onCreate's
    }

    @Override
    public Dialog onCreateDialog(final Bundle savedInstanceState) {

        _dialog = new ProgressDialog(getActivity());
        this.setStyle(STYLE_NO_TITLE, getTheme()); // You can use styles or inflate a view
        _dialog.setMessage("Spinning.."); // set your messages if not inflated from XML

        _dialog.setCancelable(false);  

        return _dialog;
    }
}

Then in your activity you set your Fragment manager and show the dialog once the wait for the server started:

FragmentManager fm = getSupportFragmentManager();
MySpinnerDialog myInstance = new MySpinnerDialog();
}
myInstance.show(fm, "some_tag");

Once your server has responded complete you will dismiss it:

myInstance.dismiss()

Remember that the progressdialog is a spinner or a progressbar depending on the attributes, read more on the api guide

Benoit Jadinon
  • 1,082
  • 11
  • 21
quinestor
  • 1,432
  • 4
  • 19
  • 40
  • ProgressDialog.show(Context context, CharSequence title, CharSequence message); Passing title parameter as empty string removes the title: ProgressDialog.show(context, "", "Loading.."); – Rajendra Oct 11 '12 at 15:32
  • 1
    Fine example, though it was still possible for me to use the back button. I think it is because of your variable dlgAlert (and where is that coming from btw? :)). Anyway - since you are extending dialogfragment, you can just call setCancelable(false) and it will work. – Lasse May 27 '14 at 12:07
  • Committing fragment transactions at an indeterministic time when the server returns a response does not seem to be fool-proof. For example, when the response comes back, the activity that hosts the fragment may be in the wrong state. Any solution? – Jonas Sep 19 '16 at 15:34
  • Make sure you're importing android.support.v4.app.DialogFragment and not android.app.DialogFragment, or you can't use getSupportFragmentManager (see http://stackoverflow.com/questions/27514338/cannot-resolve-method-showandroid-support-v4-app-fragmentmanager-java-lang-st) – StCleezy Oct 26 '16 at 03:39
  • 1
    `ProgressDialog` was deprecated in Android O https://developer.android.com/reference/android/app/ProgressDialog.html – Ivan Semkin May 20 '17 at 10:53
6

This is how I did this so that only one progress dialog can be open at a time. Based off of the answer from Suraj Bajaj

private ProgressDialog progress;



public void showLoadingDialog() {

    if (progress == null) {
        progress = new ProgressDialog(this);
        progress.setTitle(getString(R.string.loading_title));
        progress.setMessage(getString(R.string.loading_message));
    }
    progress.show();
}

public void dismissLoadingDialog() {

    if (progress != null && progress.isShowing()) {
        progress.dismiss();
    }
}

I also had to use

protected void onResume() {
    dismissLoadingDialog();
    super.onResume();
}
Isaac Zais
  • 583
  • 4
  • 13
  • 3
    `ProgressDialog` was deprecated in Android O https://developer.android.com/reference/android/app/ProgressDialog.html – Ivan Semkin May 20 '17 at 10:54