Search code examples
androidmultithreadingprogressdialogandroid-custom-view

Custom view and Progress dialog with threading in Android


I have a custom view on which I draw words and images of different sizes. Because I need to perform all kind of calculations on various user actions and they can last 3-4 seconds, I need to implement a way to display a progress dialog while the user is waiting.

The scenario is like this: the user adds some text and images for instance and I need to resize them until they fit the available view's space. This is all done on a method of my custom view.

What would be the best way to use threading and indeterminate progress dialog in my case?

Should I use a asynctask and call it each time an operation is made? Use simple threads? I have never used any threading in a View


Solution

  • You basically have two options. It's not easy to judge which is best.

    AsyncTask is certainly an option here. The nice part is that it structures the synchronization with your UI for you. It passes your calculation result from doInBackground() (which runs concurrently) to onPostExecute() (which runs on the UI thread) so you can perform your calculations and update your UI safely. It also allows you to indicate background processing progress on the UI thread via the publisProgress() / onProgressUpdate() method pair.

    But: The behaviour of AsyncTask has changed twice between API 1 and API 17. Depending on the Android version the device runs, by default, several AsyncTasks can run in parallel or not. You'll have to use executeOnExecutor() if this matters for you; this call was introduced for API 11 which means you'll have to deal with reflection if you want to support APIs before 11.

    Your second option is to have an explicit worker Thread. The appeal of this approach is that you have a dedicated Thread for a task which frequently occurs in your app and needs to be done in background. However, you'll have to deal with all the UI synchronization issues yourself. That's not difficult if you're disciplined. If your Thread knows the View objects which need to be modified, it can use the View.post(), View.postDelayed() etc methods to schedule fragments of code which have a reference to the view and will be executed on the UI thread.

    Regardless of which approach you choose, you're additionally facing two effects.

    • Android will run both your Thread and your AsyncTask with a background priority, which, if they are CPU intensive, will lead to a ten-fold execution time if you don't adjust it. For a detailed discussion, see my answer to AsyncTask, must it take such a performance penalty hit…?.

    • You need to be careful about View references in asynchronous tasks. It's posiible the View does not exist anymore because the user pressed Back or your Activity was re-created due to a configuration change aka e.g. device rotation. What this means is that you're often giving the user a way to start many of your threads by leaving and re-entering your Activity very quickly, adding more and more Threads which hold references to View objects which aren't visible any more. If you want to be clever and your computation takes long, you may (it really depends) want to re-attach your Thread to the new Activity. It's safe to ignore this for now if you make sure your Thread ends in a clean manner and frees all resources if your Activity is long gone.