众所周知,android 是不允许在主线程(UI线程)上执行耗时操作的,这样导致界面卡顿,影响用户体验
如果你尝试在主线程执行网络请求,android 会给你抛出异常
当然 android 官方也有一些解决方案,比如 Loader AsyncTask ,不过在我看来就是跟渣一样,学习成本高,难以理解,我记得我最初研究者东西花了老半天精力,后来随着代码的积累,对以移动开发也有了自己的体会,于是自己写了一个操作类
这个类,使用 Thread + HandlerThread 实现,异步执行,任务在自创线程,回调在主线程, 重复使用,
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
/**
* 一条工作线程,可以用来执行网络等耗时操作
*
* @author Yichou 2015-11-18
*
*/
public final class WorkThread implements Callback {
public static final Logger log = Logger.create("WorkThread");
private HandlerThread mThread;
private Handler mHandler;
private static final Handler mUiHandler = new Handler(Looper.getMainLooper());
public WorkThread() {
this("WorkThread");
}
public WorkThread(String name) {
mThread = new HandlerThread(name);
mThread.start();
mHandler = new Handler(mThread.getLooper(), this);
mHandler.sendEmptyMessage(0);
}
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case 0:
log.i("Hello I am worker, just give me a task.");
break;
default:
return false;
}
return true;
}
/**
* 任务完成回调,UI线程
*
* @author Jainbin
*
*/
public interface IFinishCallback {
public void onFinish(Object result);
}
/**
* 执行任务回调,任务线程
*
* @author Jainbin
*
*/
public interface IDoCallback {
public abstract Object onDo(Object doParam);
}
private class FinishRunable implements Runnable {
private Object mData;
private IFinishCallback mCallback;
private FinishRunable(IFinishCallback cb, Object data) {
mCallback = cb;
mData = data;
}
@Override
public void run() {
mCallback.onFinish(mData);
}
}
private class DoRunable implements Runnable {
private IDoCallback mDoCallback;
private IFinishCallback mFinishCallback;
private Object mDoData;
private DoRunable(IDoCallback cb, Object data, IFinishCallback cb2) {
mDoCallback = cb;
mDoData = data;
mFinishCallback = cb2;
}
@Override
public void run() {
Object ret = mDoCallback.onDo(mDoData);
mUiHandler.post(new FinishRunable(mFinishCallback, ret));
}
}
public void postCb(IDoCallback cb, Object doData, IFinishCallback cb2) {
mHandler.post(new DoRunable(cb, doData, cb2));
}
private class IRunable implements Runnable {
Runnable taskRunnable;
Runnable callbackRunnable;
public IRunable(Runnable task, Runnable callback) {
this.taskRunnable = task;
this.callbackRunnable = callback;
}
@Override
public void run() {
taskRunnable.run();
mUiHandler.post(callbackRunnable);
}
}
public void postDelay(Runnable r, long delayMillis) {
mHandler.postDelayed(r, delayMillis);
}
/**
* 发送一个带回调的任务
*
* @param task 主任务,在 sdk 线程执行
* @param callback 回调器,主任务在 sdk 线程执行完毕后,在UI线程调此回调
*/
public void postEx(Runnable task, Runnable callback) {
mHandler.post(new IRunable(task, callback));
}
public interface ITask {
/**
* 执行回调,在任务线程
*
* @param args 参数
*
* @return 执行结果,作为 {@link #onResult(Object)} 参数
*/
public Object onDo(Object... args);
/**
* 任务完成回调,在 UI 线程
*
* @param ret {@link #onDo(Object...)} 的返回值
*/
public void onResult(Object ret);
}
// public static class CommonTask implements ITask {
// private ProgressDialog mDialog;
//
// public CommonTask showDialog(Activity activity, String msg) {
// mDialog = new Prgre
// dialog = Common.createLoadingDialog(activity);
// dialog.show();
// return this;
// }
//
// @Override
// public Object onDo(Object... args) {
// // TODO Auto-generated method stub
// return null;
// }
//
// @Override
// public void onResult(Object ret) {
// // TODO Auto-generated method stub
//
// }
//
// }
private class ITaskRunable implements Runnable {
private ITask mTask;
private Object[] mArgs;
private Object mRet;
private ITaskRunable(ITask task, Object... args) {
this.mTask = task;
this.mArgs = args;
}
@Override
public void run() {
mRet = mTask.onDo(mArgs);
mUiHandler.post(new Runnable() {
@Override
public void run() {
mTask.onResult(mRet);
}
});
}
}
/**
* 2016-1-5 by yichou
*
* @param task 任务回调器
* @param args 参数
*/
public void postTask(ITask task, Object... args) {
mHandler.post(new ITaskRunable(task, args));
}
public void postTask(ITask task) {
mHandler.post(new ITaskRunable(task, (Object[])null));
}
public void postTaskDelay(int t, ITask task) {
mHandler.postDelayed(new ITaskRunable(task, (Object[])null), t);
}
public void post(Runnable r) {
mHandler.post(r);
}
/**
* 发送一个任务到UI线程
*
* @param r 任务
*/
public void postToUiThread(Runnable r) {
mUiHandler.post(r);
}
public Handler getHandler() {
return mHandler;
}
public Handler getUiHandler() {
return mUiHandler;
}
public void init() {
}
public void exit() {
mThread.quit();
try {
mThread.join(3000);
} catch (InterruptedException e) {
}
log.i("join finish!");
log.d("exited");
}
private static final Singleton<WorkThread> gDefault = new Singleton<WorkThread>() {
@Override
protected WorkThread create() {
return new WorkThread();
}
};
public static WorkThread getDefault() {
return gDefault.get();
}
}
调用实例:
void showIp() {
WorkThread.getDefault().postTask(new WorkThread.ITask() {
@Override
public void onResult(Object ret) {
new AlertDialog.Builder(getActivity())
.setTitle("IP信息").setMessage("" + ret)
.setPositiveButton(R.string.ok, null)
.create().show();
}
@Override
public Object onDo(Object... args) {
return IpUtil.getIpInfoFrom138();
}
});
}