1

I have seen code examples where a Runnable is posted to the UI thread where we are presumably already executing on the main UI thread. For example, here the top answer recommends posting the runnable. I understand that this means the runnable will be posted at the end of the message queue, but I'm not really sure what that means in the context of posting it from the UI thread itself.

It seems like just about anything could be posted as a runnable so how do we know when we must post? What are the situations where this is recommended or required practice?

Community
  • 1
  • 1
Steve M
  • 9,296
  • 11
  • 49
  • 98

2 Answers2

2

The bottom line is that by posting a runnable, you wait for the queued UI changes to finish so that the view is updated and idle.

Case 1: You are trying to access parts of the views at some point when they are not available yet eg. You want the size of the layout in the onCreate(), the view has been initialized but not measured or drawn. In such case, you want to execute the code when the view is drawn and ready. By posting a runnable on the UI thread, you are delaying the execution of the code till that view is drawn and ready.

Case 2: Many API calls in Android cause the view/layout to change and redrawn. For eg. calling notifyDataSetChanged() will redraw the list items. Android doesn't draw it right away, but waits for the UI thread to be idle (someething like posting a runnable on the UI thread). In such cases, if you call method A which performs some action on the list, then the values returned may not be accurate as the changed view has not been drawn or layout yet. In such cases you post a runnable, which executes after the UI queue has completed (which basically means the changed view has been drawn)

Amulya Khare
  • 7,718
  • 2
  • 23
  • 38
  • Good answer - if I'm remembering correctly though, I have ran into Case 1 situations where using post didn't work consistently, ie sometimes the height of the view would still return 0 and I had to use a ViewTreeObserver instead like http://stackoverflow.com/questions/7733813/how-can-you-tell-when-a-layout-has-been-drawn. – Steve M Dec 20 '13 at 12:23
1

The only time posting to the UI thread is required is when UI elements need to be changed and the code isn't already executing on the UI thread (as you most likely realize). Beyond that, it's simply a matter of timing with other UI events that may have been posted to the message queue or rely on a layout or invalidation to take effect. In the example to which you linked, the call to notifyDataSetChanged() will result in UI changes for the ListView that don't take effect until the next layout, and, via AdapterView.AdapterDataSetObserver.onChanged(), it calls requestLayout(). Posting the command to go to the bottom of the list ensures that the command is not executed until after the requested layout and resultant UI changes are made.

Dave
  • 4,282
  • 2
  • 19
  • 24
  • That would imply (to me) that some of the UI changes from notifyDataSetChanged are postDelayed() and we could cause problems (or at least not get the order we expect) by immediately executing on the main thread. Is that correct thinking? To be correct should we always post anything that updates the UI? – Steve M Dec 20 '13 at 03:59
  • I'm skimming through the source code a bit now, and nothing is actually posted. I will update my answer shortly to be more accurate, but the general idea is the same in that it's a matter of timing. If the order of UI operations matters, then it is often reasonable to use the post mechanism. – Dave Dec 20 '13 at 04:04