1 package org.robolectric.shadows; 2 3 import static org.robolectric.util.reflector.Reflector.reflector; 4 5 import android.os.Handler; 6 import android.os.Looper; 7 import android.os.Message; 8 import org.robolectric.annotation.HiddenApi; 9 import org.robolectric.annotation.Implementation; 10 import org.robolectric.annotation.Implements; 11 import org.robolectric.annotation.LooperMode; 12 import org.robolectric.annotation.RealObject; 13 import org.robolectric.shadow.api.Shadow; 14 import org.robolectric.util.Scheduler; 15 import org.robolectric.util.reflector.ForType; 16 17 /** 18 * The shadow {@link Message} for {@link LooperMode.Mode.LEGACY}. 19 * 20 * <p>In {@link LooperMode.Mode.LEGACY}, each Message is associated with a Runnable posted to the 21 * {@link Scheduler}. 22 * 23 * @see ShadowLooper 24 * @see ShadowLegacyMessageQueue 25 */ 26 @Implements(value = Message.class, isInAndroidSdk = false) 27 public class ShadowLegacyMessage extends ShadowMessage { 28 @RealObject private Message realMessage; 29 private Runnable scheduledRunnable; 30 unschedule()31 private void unschedule() { 32 Handler target = realMessage.getTarget(); 33 34 if (target != null && scheduledRunnable != null) { 35 shadowOf(target.getLooper()).getScheduler().remove(scheduledRunnable); 36 scheduledRunnable = null; 37 } 38 } 39 40 /** 41 * Hook to unscheduled the callback when the message is recycled. Invokes {@link #unschedule()} 42 * and then calls through to the package private method {@link Message#recycleUnchecked()} on the 43 * real object. 44 */ 45 @HiddenApi 46 @Implementation recycleUnchecked()47 public void recycleUnchecked() { 48 49 unschedule(); 50 reflector(MessageReflector.class, realMessage).recycleUnchecked(); 51 } 52 53 @Override setScheduledRunnable(Runnable r)54 public void setScheduledRunnable(Runnable r) { 55 scheduledRunnable = r; 56 } 57 58 @Override getNext()59 public Message getNext() { 60 return reflector(MessageReflector.class, realMessage).getNext(); 61 } 62 63 @Override setNext(Message next)64 public void setNext(Message next) { 65 reflector(MessageReflector.class, realMessage).setNext(next); 66 } 67 shadowOf(Looper looper)68 private static ShadowLooper shadowOf(Looper looper) { 69 return Shadow.extract(looper); 70 } 71 72 /** Accessor interface for {@link Message}'s internals. */ 73 @ForType(Message.class) 74 interface LegacyMessageReflector { 75 markInUse()76 void markInUse(); 77 recycle()78 void recycle(); 79 recycleUnchecked()80 void recycleUnchecked(); 81 } 82 } 83