1

My app has a not that frequent operation that is executed on the UI threads and takes long time (up to 3 secs). I want to display an animated 'wait' indications during that time. For example, a rotating spinner. No need to display the actual progress, just a fix speed animation.

I created a custom dialog that pops up during the long operation and it has this layout

<?xml version="1.0" encoding="utf-8"?>
<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/spinner"
    style="?android:attr/progressBarStyleLarge"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

Problem is that it does not spin. How do I make it spin, even if the UI thread is busy?

I tried to create a chain on events to increment it but I get only two events, probably because the UI thread is busy.

// In the custom dialog class. mProgressBar is the ProgressBar in the layout.
// Called externally once when the dialog is shown
public void tick() {
    mProgressBar.incrementProgressBy(10);
    mProgressBar.postDelayed(new Runnable() {
        @Override
        public void run() {
            // Not a recursion since it's done in a future event.
            tick();
        }
    }, 100);
}

What is a simple way to achieve this animation? Will a frame by frame animation be easier to do?

user1139880
  • 1,828
  • 3
  • 18
  • 27

3 Answers3

1

Use AsyncTask http://developer.android.com/guide/topics/fundamentals/processes-and-threads.html It is not spin because it is executing in UI thread

Geralt_Encore
  • 3,721
  • 2
  • 31
  • 46
  • Do you mean calling mProgressBar.incrementProgressBy(10); from an async task? Will the spinner be updated on screen immediately after incrementProgressBy() is called even if the UI thread is busy? – user1139880 Mar 26 '12 at 16:44
  • Nope, you should implement your own AsyncTask where in onPreExecute method you should set up your spinner, in doInBackground method you should do all you work and in onPostExecute get result and dismiss spinner. There are a lot of information about this theme in internet, just google it – Geralt_Encore Mar 26 '12 at 16:57
  • Note the answer I expected but probably the right thing to do (of loading the work to an async task). Marking as the answer. – user1139880 Mar 26 '12 at 22:34
1

You may need to set true value to the android:indeterminate property in xml or code

Volodymyr Lykhonis
  • 2,936
  • 2
  • 17
  • 13
1

Android: you're doing it wrong...

If you do something that takes a long time on the UI thread, your app freezes. Since you've locked the UI thread, you can't make anything animate (you're lucky to get two ticks), you can't make your app respond to touches or key presses, and your users will see an ANR screen (horrible user experience). Don't ever do any long running task on the UI thread, there is never any good reason to do so.

I'm guessing you want to do the task on the UI thread because what you display depends on the outcome of the task? In that case display a spinner on the main thread, run the task in the background (AsyncTask was designed for exactly this), and then only update you're UI after the task finishes. Same end result without the horrible user experience.

Sam Judd
  • 7,317
  • 1
  • 38
  • 38
  • The long task (up to 3 seconds) I am doing is restoring default preferences. The app has 30 or so preferences and when the user selects a Restore Settings action, each of the 30 preferences is set to its default value. Each of these preferences changes triggers the preferences listener in the main app that does the necessary handling of this preference change. These handlers are UI related and thus runs on the UI thread. I guess I could break the 30 settings to individual UI events (e.g. via the post() method) so the UI thread does not block for too long. – user1139880 Mar 26 '12 at 19:30
  • How (or maybe why) are the handlers UI related? Even a bunch of small UI changes should not block for three seconds. Are you setting and committing each preference individually or all at once? – Sam Judd Mar 26 '12 at 20:09
  • One commit at the end. Some of the settings are widgets related and they generate bitmap files and updated the remote views (I am using custom fonts, not supported by Remote Views. Have to generate two image files, one for portrait and one for landscape for each widget size currently in use). – user1139880 Mar 26 '12 at 22:31
  • Ah generate the bitmaps in the background? – Sam Judd Mar 26 '12 at 22:52