1 package org.coolreader.crengine;
2 
3 import android.os.Handler;
4 import android.util.Log;
5 
6 /**
7  * Schedulable cancelable replaceable task.
8  * Can schedule execution of runnable.
9  * When previously scheduled runnable was not yet executed, it's being canceled and being replaced with new one.
10  */
11 public class DelayedExecutor {
12 
13 	public static final Logger log = L.create("dt", Log.INFO);
14 
15 	private boolean isBackground;
16 	private Handler handler;
17 	private Runnable currentTask;
18 	private String name;
19 
getHandler()20 	private Handler getHandler() {
21 		if (handler != null)
22 			return handler;
23 		if (isBackground)
24 			handler = BackgroundThread.getBackgroundHandler();
25 		else
26 			handler = BackgroundThread.getGUIHandler();
27 		if (handler == null)
28 			throw new RuntimeException("Cannot get handler");
29 		return handler;
30 	}
31 
createBackground(String name)32 	public static DelayedExecutor createBackground(String name) {
33 		DelayedExecutor task = new DelayedExecutor(true, name);
34 		return task;
35 	}
36 
createGUI(String name)37 	public static DelayedExecutor createGUI(String name) {
38 		DelayedExecutor task = new DelayedExecutor(false, name);
39 		return task;
40 	}
41 
42 	/**
43 	 * Run ASAP.
44 	 * @param task is task to execute.
45 	 */
post(final Runnable task)46 	public void post(final Runnable task) {
47 		postDelayed(task, 0L);
48 	}
49 
50 	/**
51 	 * Run delayed.
52 	 * @param task is task to execute delayed.
53 	 * @param delay is delay, milliseconds.
54 	 */
postDelayed(final Runnable task, final long delay)55 	public void postDelayed(final Runnable task, final long delay) {
56 		Runnable myTask = new Runnable() {
57 			@Override
58 			public void run() {
59 				try {
60 					if (currentTask != null) {
61 						log.v("Running task " + toString());
62 						task.run();
63 						log.v("Done task " + toString());
64 					} else {
65 						log.w("Skipping probably canceled task " + toString());
66 					}
67 				} catch (Exception e) {
68 					log.e("Exception while executing task", e);
69 				}
70 			}
71 
72 			@Override
73 			public String toString() {
74 				return name + " " + task.hashCode();
75 			}
76 		};
77 		synchronized(this) {
78 			if (currentTask != null) {
79 				log.d("Cancelling pending task " + currentTask);
80 				getHandler().removeCallbacks(currentTask); // cancel pending task, replace with new one
81 			}
82 			currentTask = myTask;
83 			if (delay > 0) {
84 				log.d("Posting delayed task " + currentTask + " delay=" + delay);
85 				getHandler().postDelayed(currentTask, delay);
86 			} else {
87 				log.d("Posting task " + currentTask);
88 				getHandler().post(currentTask);
89 			}
90 		}
91 	}
92 
cancel()93 	public void cancel() {
94 		synchronized(this) {
95 			if (currentTask != null) {
96 				log.d("Cancelling pending task " + currentTask);
97 				getHandler().removeCallbacks(currentTask); // cancel pending task, replace with new one
98 				currentTask = null;
99 			}
100 		}
101 	}
102 
DelayedExecutor(boolean isBackground, String name)103 	private DelayedExecutor(boolean isBackground, String name) {
104 		this.isBackground = isBackground;
105 		this.name = name;
106 	}
107 }
108