0

Note: Read before marking as "duplicate"

So according to this android the dev site, ProgressDialog is deprecated due to:

This class was deprecated in API level 26. 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

But it doesn't really work out for me.

I DON'T want my user interacting with my app in some cases. I don't want him leaving the current activity. Take a "Create new Recipe" page for an example. It saves it to the database, when it's done it goes back to the main page, where it's displaying all the recipies from the database, and the recipe he created isn't showing in the list yet (since it's not done saving to the database), hence confusing the user.

So in the case mentioned above, am I forced to use something deprecated? Or is there an alternative?

Ali Bdeir
  • 4,151
  • 10
  • 57
  • 117

3 Answers3

1

I don't want him leaving the current activity

You do not have much of a choice. The user can navigate to other apps whether you like it or not.

the recipe he created isn't showing in the list yet (since it's not done saving to the database), hence confusing the user.

Then perhaps you should be updating the list in tandem with updating the database. For example, the list could be operating off of an ArrayList<Recipe> and not be dependent upon the database I/O to be completed to show the newly-created recipe.

Moreover, if database I/O for saving a recipe is taking more than a few hundred milliseconds, you need to focus on why your database I/O is taking so long. Saving a recipe to a local database should not need a ProgressDialog in the first place.

So in the case mentioned above, am I forced to use something deprecated? Or is there an alternative?

Don't block the UI waiting for I/O to complete.

Otherwise, create your own ProgressDialog equivalent, using an AlertDialog. Or, stick with the deprecated ProgressDialog.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • I'm using Firebase, and depending on whether or not the user has fast or slow internet is very bad practice. And FirebaseRecyclerAdapter doesn't really support adding items manually. Also that was an example, I'm saving something much more complicated – Ali Bdeir Aug 21 '17 at 15:08
  • And notice how I said I don't want him leaving the *activity*, not the application. – Ali Bdeir Aug 21 '17 at 15:10
  • 1
    @Ab_: "I'm using Firebase, and depending on whether or not the user has fast or slow internet is very bad practice" -- use a local cache with background syncing. "And FirebaseRecyclerAdapter doesn't really support adding items manually" -- then don't use it. Use something else that offers greater flexibility and can work off of your local cache. "And notice how I said I don't want him leaving the activity, not the application" -- leaving the application is a common subset of "leaving the activity" scenarios. – CommonsWare Aug 21 '17 at 15:11
  • I'm not migrating my app to a whole new database and rewriting the code just for a progress dialog, and it doesn't support local cache and background syncing either. And the important thing is he doesn't see the previous activity and getting confused, not whether he quits the app or not. – Ali Bdeir Aug 21 '17 at 15:14
  • 1
    @Ab_: "I'm not migrating my app to a whole new database and rewriting the code just for a progress dialog" -- you should be doing it for offline access and user privacy (via making syncing the data to Firebase be optional, rather than mandatory). Improving the UI flow is merely a side benefit. – CommonsWare Aug 21 '17 at 15:17
1

You can create your own DialogFragment, here my solution for this case:

  1. Create dialog class

class BaseProgressDialog : DialogFragment() {

    companion object {
        const val DIALOG_TAG = "BaseProgressDialogFragment"
    }

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        return activity?.let {
            val builder = AlertDialog.Builder(it, R.style.MainAlertDialog)
            val inflater = requireActivity().layoutInflater
            val dialogView = inflater.inflate(R.layout.progress_dialog, null)

            builder.setView(dialogView)
            builder.create()
        } ?: throw IllegalStateException("Activity cannot be null")
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        dialog?.setCanceledOnTouchOutside(false)
        dialog?.setCancelable(false)
        return super.onCreateView(inflater, container, savedInstanceState)
    }

    override fun onResume() {
        super.onResume()
        val size = resources.getDimensionPixelSize(R.dimen.size_80dp)
        dialog?.window?.setLayout(size, size)
    }
}
  1. Create style in your styles.xml
<style name="MainAlertDialog" parent="Theme.AppCompat.Light.Dialog.Alert">
    <item name="android:windowBackground">@drawable/bg_alert_dialog</item>
</style>
  1. Create background for your dialog bg_alert_dialog.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="?attr/colorSecondary"/>
    <corners android:radius="@dimen/radius_10dp" />
</shape>
  1. Create layout for dialog progress_dialog.xml
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/bg_alert_dialog"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="@dimen/padding_16dp">

    <com.google.android.material.progressindicator.CircularProgressIndicator
        android:layout_width="@dimen/size_40dp"
        android:layout_height="@dimen/size_40dp"
        android:indeterminate="true"
        app:indicatorColor="?attr/colorPrimary" />

</LinearLayout>
  1. Call dialog in the Fragment
private var progressDialog = BaseProgressDialog()
activity?.let {
   progressDialog.show(it.supportFragmentManager, BaseProgressDialog.DIALOG_TAG)
}

And this is what it will look like:

enter image description here

tasjapr
  • 632
  • 4
  • 13
0

If you don't feel like creating your own progress dialog, you can use this library I wrote called PleaseWait. It's designed using Material Design and supports light/dark/determinate/indeterminate modes. It looks like this:

Preview

Tashila Pathum
  • 109
  • 2
  • 11