【Android】用HandlerThread模拟AsyncTask功能(ThreadTask)
前言
AsyncTask是个好东西,能处理绝大多数应用线程和更新UI的任务,由于其内部使用了静态线程池,如果你有一堆异步任务(例如全局定时更新数据、同一个Activity中多个AsyncTask同时执行)其中有不能马上执行完的情况(例如网络请求超时),那就糟了,其他任务都还等着呢,就会出现任务卡住的情况。此时就需要直接上Thread了,这里参考AsyncTask的API封装了一个ThreadTask,便于必要时代码替换,欢迎交流!
声明
欢迎转载,但请保留文章原始出处:)
博客园:http://www.cnblogs.com
农民伯伯: http://over140.cnblogs.com
正文
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
public abstract class ThreadTask<Params, Progress, Result> {
private HandlerThread mHandlerThread;
private TaskHandler mHandler;
private TaskHandler mUiHandler;
private Params[] mParams;
public ThreadTask() {
mHandlerThread = new HandlerThread("ThreadTask", android.os.Process.THREAD_PRIORITY_BACKGROUND);
mHandlerThread.start();
mHandler = new TaskHandler(mHandlerThread.getLooper());
mUiHandler = new TaskHandler(Looper.getMainLooper());
}
protected abstract Result doInBackground(Params... params);
protected void onPreExecute() {
}
protected void onProgressUpdate(Progress... values) {
}
protected final void publishProgress(Progress... values) {
mUiHandler.obtainMessage(MESSAGE_PROGRESS, values).sendToTarget();
}
protected void onPostExecute(Result result) {
}
public final boolean isCancelled() {
return mHandlerThread.isInterrupted();
}
public final void cancel(boolean mayInterruptIfRunning) {
if (!mHandlerThread.isInterrupted()) {
try {
mHandlerThread.quit();
mHandlerThread.interrupt();
} catch (SecurityException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
onCancelled();
}
protected void onCancelled() {
}
public void execute(Params... params) {
mParams = params;
onPreExecute();
mHandler.sendEmptyMessage(MESSAGE_INBACKGROUND);
}
private static final int MESSAGE_INBACKGROUND = 0;
private static final int MESSAGE_POSTEXECUTE = 1;
private static final int MESSAGE_PROGRESS = 2;
private class TaskHandler extends Handler {
public TaskHandler(Looper looper) {
super(looper);
}
@SuppressWarnings("unchecked")
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_INBACKGROUND:
mUiHandler.obtainMessage(MESSAGE_POSTEXECUTE, doInBackground(mParams)).sendToTarget();
break;
case MESSAGE_POSTEXECUTE:
onPostExecute((Result) msg.obj);
mHandlerThread.quit();
break;
case MESSAGE_PROGRESS:
onProgressUpdate((Progress[]) msg.obj);
break;
}
}
}
}
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
public abstract class ThreadTask<Params, Progress, Result> {
private HandlerThread mHandlerThread;
private TaskHandler mHandler;
private TaskHandler mUiHandler;
private Params[] mParams;
public ThreadTask() {
mHandlerThread = new HandlerThread("ThreadTask", android.os.Process.THREAD_PRIORITY_BACKGROUND);
mHandlerThread.start();
mHandler = new TaskHandler(mHandlerThread.getLooper());
mUiHandler = new TaskHandler(Looper.getMainLooper());
}
protected abstract Result doInBackground(Params... params);
protected void onPreExecute() {
}
protected void onProgressUpdate(Progress... values) {
}
protected final void publishProgress(Progress... values) {
mUiHandler.obtainMessage(MESSAGE_PROGRESS, values).sendToTarget();
}
protected void onPostExecute(Result result) {
}
public final boolean isCancelled() {
return mHandlerThread.isInterrupted();
}
public final void cancel(boolean mayInterruptIfRunning) {
if (!mHandlerThread.isInterrupted()) {
try {
mHandlerThread.quit();
mHandlerThread.interrupt();
} catch (SecurityException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
onCancelled();
}
protected void onCancelled() {
}
public void execute(Params... params) {
mParams = params;
onPreExecute();
mHandler.sendEmptyMessage(MESSAGE_INBACKGROUND);
}
private static final int MESSAGE_INBACKGROUND = 0;
private static final int MESSAGE_POSTEXECUTE = 1;
private static final int MESSAGE_PROGRESS = 2;
private class TaskHandler extends Handler {
public TaskHandler(Looper looper) {
super(looper);
}
@SuppressWarnings("unchecked")
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_INBACKGROUND:
mUiHandler.obtainMessage(MESSAGE_POSTEXECUTE, doInBackground(mParams)).sendToTarget();
break;
case MESSAGE_POSTEXECUTE:
onPostExecute((Result) msg.obj);
mHandlerThread.quit();
break;
case MESSAGE_PROGRESS:
onProgressUpdate((Progress[]) msg.obj);
break;
}
}
}
}
代码说明:
由于onPreExecute和onPostExecute都在在主线程执行,又要保证执行的顺序,所以采用Handler来控制执行顺序,根据Loop的不同,Handler能切换在子线程中执行代码还是在主线程中执行代码。
文章
Android AsyncTask完全解析,带你从源码的角度彻底理解
后期维护
2014-08-05 正常流程走完以后忘了调用HandlerThread的quit,代码已经更新。
结束
除了不受线程池控制以外,还能被真正的cancel掉(AsyncTask是不能的,只是一个标记),写的有些仓促,难免bug,欢迎反馈!