对于android开发中经常遇到的异步定时任务的问题,android提供了丰富的工具来支持,例如Handler, HandlerThread, AsyncTask, Loader, ExecutorService,详细可以参考这篇文章:Android线程任务剖析
简单的分下类:
A. 处理线程之间交互,例如主线程与用户线程,用户线程之间
包括:Handler, HandlerThread, AsyncTask, Loader
区别:
- Handler,HandlerThread:是单线程的,用消息队列的方式在工作线程中处理任务
- AsyncTask:处理工作线程与UI线程的交互,有自己的线程池
- Loader:处理了线程与Activity生命周期的关系,AsyncTaskLoader是AsyncTask的升级版
B. 线程池管理,定时任务等
包括:ExecutorService, ScheduledThreadPoolExecutor
上面的A部分可以理解为是适用于app开发中提升开发效率的工具,它主要解决了大部分App的使用场景。如果你开发一个简单的App那么A部分也就够用了。至于B部分会是较为灵活,且功能强大的线程工具了,B部分只关注线程管理,其它的事情需要你自己关注了。你可以用B结合A一起定制成一款适用于你自己App的异步任务管理
熟悉上面介绍的android A和B的线程工具类,你就基本可以打遍天下都不怕了,当然gitHub上面有很多的线程框架,你用它们当然最快了。我个人推荐这个android-priority-jobqueue
如果你想自己自定义延迟任务该如何运行,以下提供一个例子供你参考,核心思想是使用Object.wailt(long timemills)
一段demo代码,适用于排队处理多个定时任务,支持添加任务,取消当前任务,关闭功能:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
public class SchedulerThread extends Thread { private static final String NAME = "schedule_thread"; private LinkedBlockingQueue<RefreshTask> mTaskQueue = new LinkedBlockingQueue<RefreshTask>(); private final Object mLock = new Object(); private boolean mExitFlag = false; private RefreshTask mCurRefreshTask; public SchedulerThread() { setDaemon(true); setName(NAME); setPriority(Thread.MIN_PRIORITY); } /** * 添加定时任务 * @param task */ public void offerTask(RefreshTask task) { if(mExitFlag) { Log.w(NAME, "reject task, current thread is exit!"); return; } mTaskQueue.offer(task); } public void cancelCurrentTask() { if(mCurRefreshTask != null) { mCurRefreshTask.setCancelled(); } synchronized (mLock) { mLock.notify(); } } /** * 让整个刷新线程退出 */ public void exit() { mTaskQueue.clear(); mTaskQueue.offer(new ExitTask()); mExitFlag = true; synchronized (mLock) { mLock.notify(); } } @Override public void run() { try { while ((mCurRefreshTask = mTaskQueue.take()) != null) { if(mCurRefreshTask.nextRefreshInterval() > 0 && !mCurRefreshTask.isCancelled()) { if(mCurRefreshTask.nextRefreshInterval() != RefreshTask.NEXT_REFRESH_IMMEDIATELY) { synchronized (mLock) { try { mLock.wait(mCurRefreshTask.nextRefreshInterval()); } catch (InterruptedException e) { e.printStackTrace(); } } } } //如果当前任务取消,则直接跳过该任务的执行,跳到下一个任务 if(mCurRefreshTask.isCancelled()) { Log.w(NAME, "on task cancelled:" + mCurRefreshTask.taskName); continue; } //break if(mExitFlag) { break; } //do something mCurRefreshTask.run(); //break if(mExitFlag) { break; } } } catch (InterruptedException e) { e.printStackTrace(); } //exit now Log.d(NAME, "exit!!!....."); } /** * 一个退出任务 */ private class ExitTask extends RefreshTask { public ExitTask() { super("exit-task", -1, null); } @Override public void run() { //do nothing } } /** * 刷新任务,可以设置下一次刷新时间 */ public static abstract class RefreshTask implements Runnable { public static final int NEXT_REFRESH_IMMEDIATELY = 0; private long nextRefreshIntervals = NEXT_REFRESH_IMMEDIATELY; private boolean isCancelled = false; private String taskName; private RefreshResultListener refreshResultListener; public RefreshTask(String taskName, long timeIntervals, RefreshResultListener refreshResultListener) { this.taskName = taskName; this.nextRefreshIntervals = timeIntervals; this.refreshResultListener = refreshResultListener; } public long nextRefreshInterval() { return nextRefreshIntervals; } public RefreshResultListener getRefreshResultListener() { return refreshResultListener; } public boolean isCancelled() { return isCancelled; } public void setCancelled() { isCancelled = true; } public static interface RefreshResultListener<T> { void onRefreshSuccess(T sessionInfo); void onRefreshFailed(int errCode, String errMsg); } } |