1 package com.xtremelabs.robolectric.util; 2 3 import java.util.ArrayList; 4 import java.util.Collections; 5 import java.util.List; 6 import java.util.ListIterator; 7 8 public class Scheduler { 9 private List<PostedRunnable> postedRunnables = new ArrayList<PostedRunnable>(); 10 private long currentTime = 0; 11 private boolean paused = false; 12 getCurrentTime()13 public long getCurrentTime() { 14 return currentTime; 15 } 16 pause()17 public void pause() { 18 paused = true; 19 } 20 unPause()21 public void unPause() { 22 paused = false; 23 advanceToLastPostedRunnable(); 24 } 25 isPaused()26 public boolean isPaused() { 27 return paused; 28 } 29 postDelayed(Runnable runnable, long delayMillis)30 public void postDelayed(Runnable runnable, long delayMillis) { 31 if (paused || delayMillis > 0) { 32 postedRunnables.add(new PostedRunnable(runnable, currentTime + delayMillis)); 33 Collections.sort(postedRunnables); 34 } else { 35 runnable.run(); 36 } 37 } 38 post(Runnable runnable)39 public void post(Runnable runnable) { 40 postDelayed(runnable, 0); 41 } 42 postAtFrontOfQueue(Runnable runnable)43 public void postAtFrontOfQueue(Runnable runnable) { 44 if (paused) { 45 postedRunnables.add(0, new PostedRunnable(runnable, currentTime)); 46 } else { 47 runnable.run(); 48 } 49 } 50 remove(Runnable runnable)51 public void remove(Runnable runnable) { 52 ListIterator<PostedRunnable> iterator = postedRunnables.listIterator(); 53 while (iterator.hasNext()) { 54 PostedRunnable next = iterator.next(); 55 if (next.runnable == runnable) { 56 iterator.remove(); 57 } 58 } 59 } 60 advanceToLastPostedRunnable()61 public boolean advanceToLastPostedRunnable() { 62 if (enqueuedTaskCount() < 1) { 63 return false; 64 } 65 66 return advanceTo(postedRunnables.get(postedRunnables.size() - 1).scheduledTime); 67 } 68 advanceToNextPostedRunnable()69 public boolean advanceToNextPostedRunnable() { 70 if (enqueuedTaskCount() < 1) { 71 return false; 72 } 73 74 return advanceTo(postedRunnables.get(0).scheduledTime); 75 } 76 advanceBy(long intervalMs)77 public boolean advanceBy(long intervalMs) { 78 long endingTime = currentTime + intervalMs; 79 return advanceTo(endingTime); 80 } 81 advanceTo(long endingTime)82 public boolean advanceTo(long endingTime) { 83 if (endingTime - currentTime < 0 || enqueuedTaskCount() < 1) { 84 return false; 85 } 86 87 int runCount = 0; 88 while (nextTaskIsScheduledBefore(endingTime)) { 89 runOneTask(); 90 ++runCount; 91 } 92 currentTime = endingTime; 93 94 return runCount > 0; 95 } 96 runOneTask()97 public boolean runOneTask() { 98 if (enqueuedTaskCount() < 1) { 99 return false; 100 } 101 102 PostedRunnable postedRunnable = postedRunnables.remove(0); 103 currentTime = postedRunnable.scheduledTime; 104 postedRunnable.run(); 105 return true; 106 } 107 runTasks(int howMany)108 public boolean runTasks(int howMany) { 109 if (enqueuedTaskCount() < howMany) { 110 return false; 111 } 112 113 while (howMany > 0) { 114 PostedRunnable postedRunnable = postedRunnables.remove(0); 115 currentTime = postedRunnable.scheduledTime; 116 postedRunnable.run(); 117 howMany--; 118 } 119 return true; 120 } 121 enqueuedTaskCount()122 public int enqueuedTaskCount() { 123 return postedRunnables.size(); 124 } 125 areAnyRunnable()126 public boolean areAnyRunnable() { 127 return nextTaskIsScheduledBefore(currentTime); 128 } 129 reset()130 public void reset() { 131 postedRunnables.clear(); 132 paused = false; 133 } 134 size()135 public int size() { 136 return postedRunnables.size(); 137 } 138 139 class PostedRunnable implements Comparable<PostedRunnable> { 140 Runnable runnable; 141 long scheduledTime; 142 PostedRunnable(Runnable runnable, long scheduledTime)143 PostedRunnable(Runnable runnable, long scheduledTime) { 144 this.runnable = runnable; 145 this.scheduledTime = scheduledTime; 146 } 147 148 @Override compareTo(PostedRunnable postedRunnable)149 public int compareTo(PostedRunnable postedRunnable) { 150 return (int) (scheduledTime - postedRunnable.scheduledTime); 151 } 152 run()153 public void run() { 154 runnable.run(); 155 } 156 } 157 nextTaskIsScheduledBefore(long endingTime)158 private boolean nextTaskIsScheduledBefore(long endingTime) { 159 return enqueuedTaskCount() > 0 && postedRunnables.get(0).scheduledTime <= endingTime; 160 } 161 } 162