2828
2929import android .os .Looper ;
3030import android .util .Log ;
31+ import org .androidannotations .annotations .SupposeBackground ;
32+ import org .androidannotations .annotations .SupposeUiThread ;
3133
3234public class BackgroundExecutor {
3335
3436 private static final String TAG = "BackgroundExecutor" ;
3537
3638 public static Executor DEFAULT_EXECUTOR = Executors .newScheduledThreadPool (2 * Runtime .getRuntime ().availableProcessors ());
3739 private static Executor executor = DEFAULT_EXECUTOR ;
38- public static final WrongThreadListener DEFAULT_WRONG_THREAD_LISTENER = new WrongThreadListener () {
39- @ Override
40- public void onUiExpected () {
41- throw new IllegalStateException ("Method invocation is expected from the UI thread" );
42- }
43-
44- @ Override
45- public void onBgExpected (String ... expectedSerials ) {
46- if (expectedSerials .length == 0 ) {
47- throw new IllegalStateException ("Method invocation is expected from a background thread, but it was called from the UI thread" );
48- }
49- throw new IllegalStateException ("Method invocation is expected from one of serials " + Arrays .toString (expectedSerials ) + ", but it was called from the UI thread" );
50- }
51-
52- @ Override
53- public void onWrongBgSerial (String currentSerial , String ... expectedSerials ) {
54- if (currentSerial == null ) {
55- currentSerial = "anonymous" ;
56- }
57- throw new IllegalStateException ("Method invocation is expected from one of serials " + Arrays .toString (expectedSerials ) + ", but it was called from " + currentSerial + " serial" );
58- }
59- };
60- private static WrongThreadListener wrongThreadListener = DEFAULT_WRONG_THREAD_LISTENER ;
40+
41+ /**
42+ * The default invocation handler for wrong thread execution.
43+ * It just throws {@link IllegalStateException} with explanation what is going wrong.
44+ *
45+ * @see #setWrongThreadListener(BackgroundExecutor.WrongThreadListener)
46+ * @see SupposeBackground
47+ * @see SupposeUiThread
48+ */
49+ public static final WrongThreadListener DEFAULT_WRONG_THREAD_LISTENER = new WrongThreadListener () {
50+ @ Override
51+ public void onUiExpected () {
52+ throw new IllegalStateException ("Method invocation is expected from the UI thread" );
53+ }
54+
55+ @ Override
56+ public void onBgExpected (String ... expectedSerials ) {
57+ if (expectedSerials .length == 0 ) {
58+ throw new IllegalStateException ("Method invocation is expected from a background thread, but it was called from the UI thread" );
59+ }
60+ throw new IllegalStateException ("Method invocation is expected from one of serials " + Arrays .toString (expectedSerials ) + ", but it was called from the UI thread" );
61+ }
62+
63+ @ Override
64+ public void onWrongBgSerial (String currentSerial , String ... expectedSerials ) {
65+ if (currentSerial == null ) {
66+ currentSerial = "anonymous" ;
67+ }
68+ throw new IllegalStateException ("Method invocation is expected from one of serials " + Arrays .toString (expectedSerials ) + ", but it was called from " + currentSerial + " serial" );
69+ }
70+ };
71+
72+ private static WrongThreadListener wrongThreadListener = DEFAULT_WRONG_THREAD_LISTENER ;
6173
6274 private static final List <Task > tasks = new ArrayList <Task >();
63- private static final ThreadLocal <String > currentSerial = new ThreadLocal <String >();
75+ private static final ThreadLocal <String > currentSerial = new ThreadLocal <String >();
6476
6577 /**
6678 * Execute a runnable after the given delay.
@@ -211,17 +223,19 @@ public static void setExecutor(Executor executor) {
211223 BackgroundExecutor .executor = executor ;
212224 }
213225
214- /**
215- * Change the WrongThreadListener.
216- * @param listener the new WrongThreadListener
217- */
218- public static void setWrongThreadListener (WrongThreadListener listener ) {
219- BackgroundExecutor .wrongThreadListener = listener ;
220- }
226+ /**
227+ * Changes the default {@link WrongThreadListener}.
228+ * To restore the default one use {@link #DEFAULT_WRONG_THREAD_LISTENER}.
229+ *
230+ * @param listener the new {@link WrongThreadListener}
231+ */
232+ public static void setWrongThreadListener (WrongThreadListener listener ) {
233+ wrongThreadListener = listener ;
234+ }
221235
222236 /**
223237 * Cancel all tasks having the specified <code>id</code>.
224- *
238+ *
225239 * @param id
226240 * the cancellation identifier
227241 * @param mayInterruptIfRunning
@@ -253,57 +267,56 @@ public static synchronized void cancelAll(String id, boolean mayInterruptIfRunni
253267 }
254268 }
255269
256- /**
257- * Checks if current thread is UI and notifies
258- * {@link BackgroundExecutor.WrongThreadListener#onUiExpected()} if it doesn't.
259- */
260- public static void checkUiThread () {
261- if (Looper .getMainLooper ().getThread () != Thread .currentThread ()) {
262- wrongThreadListener .onUiExpected ();
263- }
264- }
265-
266- /**
267- * Check if current thread is a background thread and, optionally, restrict it
268- * with passed serials. If no serials passed and current thread is UI , then
269- * {@link WrongThreadListener#onBgExpected(String...)} will be called.
270- * If current thread is not UI and serials list is empty, then method just returns.
271- * Otherwise, if method was called not during {@link Task} execution or the task has no
272- * serial, then {@link WrongThreadListener#onWrongBgSerial(String, String...)} will be called
273- * with null for the first parameter. If task has serial but passed serials don't contain that,
274- * then {@link WrongThreadListener#onWrongBgSerial(String, String...)} will be called with
275- * task's serial for the first parameter.
276- *
277- * @param serials (optional) list of allowed serials
278- */
279- public static void checkBgThread (String ... serials ) {
280- if (serials .length == 0 ) {
281- if (Looper .getMainLooper ().getThread () == Thread .currentThread ()) {
282- wrongThreadListener .onBgExpected (serials );
283- }
284- return ;
285- }
286- String current = currentSerial .get ();
287- if (current == null ) {
288- wrongThreadListener .onWrongBgSerial (null , serials );
289- return ;
290- }
291- for (String serial : serials ) {
292- if (serial .equals (current )) {
293- return ;
294- }
295- }
296- wrongThreadListener .onWrongBgSerial (current , serials );
297- }
270+ /**
271+ * Checks if the current thread is UI thread and notifies
272+ * {@link BackgroundExecutor.WrongThreadListener#onUiExpected()} if it doesn't.
273+ */
274+ public static void checkUiThread () {
275+ if (Looper .getMainLooper ().getThread () != Thread .currentThread ()) {
276+ wrongThreadListener .onUiExpected ();
277+ }
278+ }
279+
280+ /**
281+ * Checks if the current thread is a background thread and, optionally, restricts it
282+ * with passed serials. If no serials passed and current thread is the UI thread , then
283+ * {@link WrongThreadListener#onBgExpected(String...)} will be called.
284+ * If the current thread is not UI and serials list is empty, then this method just returns.
285+ * Otherwise, if the method was called not during {@link Task} execution or the task has no
286+ * serial, then the {@link WrongThreadListener#onWrongBgSerial(String, String...)} will be called
287+ * with null for the first parameter. If task has a serial but passed serials don't contain that,
288+ * then {@link WrongThreadListener#onWrongBgSerial(String, String...)} will be called with
289+ * the task's serial for the first parameter.
290+ *
291+ * @param serials (optional) list of allowed serials
292+ */
293+ public static void checkBgThread (String ... serials ) {
294+ if (serials .length == 0 ) {
295+ if (Looper .getMainLooper ().getThread () == Thread .currentThread ()) {
296+ wrongThreadListener .onBgExpected (serials );
297+ }
298+ return ;
299+ }
300+ String current = currentSerial .get ();
301+ if (current == null ) {
302+ wrongThreadListener .onWrongBgSerial (null , serials );
303+ return ;
304+ }
305+ for (String serial : serials ) {
306+ if (serial .equals (current )) {
307+ return ;
308+ }
309+ }
310+ wrongThreadListener .onWrongBgSerial (current , serials );
311+ }
298312
299313 /**
300314 * Indicates whether a task with the specified <code>serial</code> has been
301315 * submitted to the executor.
302- *
303- * @param serial
304- * the serial queue
316+ *
317+ * @param serial the serial queue
305318 * @return <code>true</code> if such a task has been submitted,
306- * <code>false</code> otherwise
319+ * <code>false</code> otherwise
307320 */
308321 private static boolean hasSerialRunning (String serial ) {
309322 for (Task task : tasks ) {
@@ -376,7 +389,7 @@ public void run() {
376389 }
377390
378391 try {
379- currentSerial .set (serial );
392+ currentSerial .set (serial );
380393 execute ();
381394 } finally {
382395 /* handle next tasks */
@@ -391,7 +404,7 @@ private void postExecute() {
391404 /* nothing to do */
392405 return ;
393406 }
394- currentSerial .set (null );
407+ currentSerial .set (null );
395408 synchronized (BackgroundExecutor .class ) {
396409 /* execution complete */
397410 tasks .remove (this );
@@ -411,14 +424,50 @@ private void postExecute() {
411424 }
412425
413426 }
414- /**
415- * A callback interface to be notified when current thread, in which method has been invoked,
416- * is wrong.
417- * @see #setWrongThreadListener(WrongThreadListener)
418- */
419- public static interface WrongThreadListener {
420- void onUiExpected ();
421- void onBgExpected (String ... expectedSerials );
422- void onWrongBgSerial (String currentSerial , String ... expectedSerials );
423- }
427+
428+ /**
429+ * A callback interface to be notified when a method invocation is expected from another thread.
430+ *
431+ * @see #setWrongThreadListener(WrongThreadListener)
432+ * @see #checkUiThread()
433+ * @see #checkBgThread(String...)
434+ * @see SupposeUiThread
435+ * @see SupposeBackground
436+ */
437+ public static interface WrongThreadListener {
438+
439+ /**
440+ * Will be called, if the method is supposed to be called from the UI-thread, but was called from a background
441+ * thread.
442+ *
443+ * @see SupposeUiThread
444+ * @see #setWrongThreadListener(WrongThreadListener)
445+ * @see #DEFAULT_WRONG_THREAD_LISTENER
446+ */
447+ void onUiExpected ();
448+
449+ /**
450+ * Will be called, if the method is supposed to be called from a background thread, but was called from the
451+ * UI-thread.
452+ *
453+ * @param expectedSerials a list of allowed serials. If any background thread is allowed the list will be empty.
454+ * @see SupposeBackground
455+ * @see #setWrongThreadListener(WrongThreadListener)
456+ * @see #DEFAULT_WRONG_THREAD_LISTENER
457+ */
458+ void onBgExpected (String ... expectedSerials );
459+
460+ /**
461+ * Will be called, if the method is supposed to be called from a background thread with one of
462+ * {@code expectedSerials}, but was called from a {@code currentSerial}. {@code currentSerial} will be null,
463+ * if it is called from a background thread without a serial.
464+ *
465+ * @param currentSerial the serial of caller thread or null if there is no serial
466+ * @param expectedSerials a list of allowed serials
467+ * @see SupposeBackground
468+ * @see #setWrongThreadListener(WrongThreadListener)
469+ * @see #DEFAULT_WRONG_THREAD_LISTENER
470+ */
471+ void onWrongBgSerial (String currentSerial , String ... expectedSerials );
472+ }
424473}
0 commit comments