@@ -411,6 +411,50 @@ public final boolean postAtFrontOfQueue(Runnable r)
411411 return sendMessageAtFrontOfQueue (getPostMessage (r ));
412412 }
413413
414+ /**
415+ * Runs the specified task synchronously.
416+ *
417+ * If the current thread is the same as the handler thread, then the runnable
418+ * runs immediately without being enqueued. Otherwise, posts the runnable
419+ * to the handler and waits for it to complete before returning.
420+ *
421+ * This method is dangerous! Improper use can result in deadlocks.
422+ * Never call this method while any locks are held or use it in a
423+ * possibly re-entrant manner.
424+ *
425+ * This method is occasionally useful in situations where a background thread
426+ * must synchronously await completion of a task that must run on the
427+ * handler's thread. However, this problem is often a symptom of bad design.
428+ * Consider improving the design (if possible) before resorting to this method.
429+ *
430+ * One example of where you might want to use this method is when you just
431+ * set up a Handler thread and need to perform some initialization steps on
432+ * it before continuing execution.
433+ *
434+ * @param r The Runnable that will be executed synchronously.
435+ *
436+ * @return Returns true if the Runnable was successfully executed.
437+ * Returns false on failure, usually because the
438+ * looper processing the message queue is exiting.
439+ *
440+ * @hide This method is prone to abuse and should probably not be in the API.
441+ * If we ever do make it part of the API, we might want to rename it to something
442+ * less funny like runUnsafe().
443+ */
444+ public final boolean runWithScissors (final Runnable r ) {
445+ if (r == null ) {
446+ throw new IllegalArgumentException ("runnable must not be null" );
447+ }
448+
449+ if (Looper .myLooper () == mLooper ) {
450+ r .run ();
451+ return true ;
452+ }
453+
454+ BlockingRunnable br = new BlockingRunnable (r );
455+ return br .postAndWait (this );
456+ }
457+
414458 /**
415459 * Remove any pending posts of Runnable r that are in the message queue.
416460 */
@@ -678,4 +722,41 @@ private static void handleCallback(Message message) {
678722 final Callback mCallback ;
679723 final boolean mAsynchronous ;
680724 IMessenger mMessenger ;
725+
726+ private static final class BlockingRunnable implements Runnable {
727+ private final Runnable mTask ;
728+ private boolean mDone ;
729+
730+ public BlockingRunnable (Runnable task ) {
731+ mTask = task ;
732+ }
733+
734+ @ Override
735+ public void run () {
736+ try {
737+ mTask .run ();
738+ } finally {
739+ synchronized (this ) {
740+ mDone = true ;
741+ notifyAll ();
742+ }
743+ }
744+ }
745+
746+ public boolean postAndWait (Handler handler ) {
747+ if (!handler .post (this )) {
748+ return false ;
749+ }
750+
751+ synchronized (this ) {
752+ while (!mDone ) {
753+ try {
754+ wait ();
755+ } catch (InterruptedException ex ) {
756+ }
757+ }
758+ }
759+ return true ;
760+ }
761+ }
681762}
0 commit comments