Android的异步任务有很多实现方法,最常见的如Handler、Thread、AsyncTask;还有一些开源项目也可以做到异步任务和线程间通信等功能,例如:EventBus、RxAndroid等,我们这里就不讨论用哪种实现方式更好,只是根据实际需求进行合适的筛选。
笔者公司的项目算是大型的互联网金融类的App,由于历史架构原因未用到一些新的开源项目,也不能盲目引入这些开源的项目,所以只能在Handler、Thread、AsyncTask中选择一个进行封装了。封装要求:调用便捷、灵活、可扩展,最重要是防止内存泄露,最好能在调用者销毁时自动中断并释放所有异步任务资源。
Handler已经不能再熟悉了,封装起来虽然更能得心应手,但是考虑时间问题觉得AsyncTask更简单,因为google已经对异步任务进行了封装,所以才有了AsyncTask这个类。但要注意的是AsyncTask是顺序执行的,也就是并不适合并发需求,如有并发需求请跳过。
整个封装简单,直接上工具类代码:
package asyncTask;
import android.util.Log;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 异步任务工具类
* 支持任务的执行与Activity生命周期进行绑定
*/
public class AsyncTaskUtil {
private static Map>> taskMap = new ConcurrentHashMap<>();
/**
* 异步任务
* @param obj 请求标识
* @param call 回调
* @param params 入参
*/
public static void doAsync(Object obj, AsyncCall
异步任务回调抽象类
package asyncTask;
public abstract class AsyncCallAbs {
//UI线程执行:在onCall之前执行
abstract void onPreCall();
//非UI线程执行:执行耗时操作
abstract T onCall(Object[] objects) throws Exception;
//非UI线程执行:用于通知进度更新
abstract void publishProgress(Integer... values);
//UI线程执行:更新进度
abstract void onProgressUpdate(Integer[] values);
//UI线程执行:异步任务执行完毕
abstract void onCallFinished(T result);
abstract void cancel(boolean mayInterruptIfRunning);
}
package asyncTask;
//Object 启动任务执行的输入参数。
//Integer 后台任务执行的百分比。
//T 后台执行任务最终返回的结果,比如String。
public class AsyncCall extends AsyncCallAbs {
private MyAsyncTask task;
public void bindTask(MyAsyncTask task){
this.task = task;
}
@Override
public T onCall(Object[] objects) throws Exception {
return null;
}
@Override
public void onCallFinished(T result) {
}
@Override
public void onPreCall() {
}
@Override
public void onProgressUpdate(Integer[] values) {
}
@Override
public void publishProgress(Integer... values) {
if(null != task)
task.publishProgress(values);
}
@Override
public void cancel(boolean mayInterruptIfRunning) {
if(null != task){
task = null;
}
}
}
AsyncTaskUtil.doAsync(this,new AsyncCall(){
@Override
public String onCall(Object[] obj) throws Exception {
for(int i=0;i<10;i++){
publishProgress(i);
Thread.sleep(200);
}
return obj[0].toString()+" "+obj[1].toString();
}
@Override
public void onCallFinished(String result) {
tv.setText(result);
}
@Override
public void onProgressUpdate(Integer[] values) {
tv.setText(values[0].toString());
}
},"hello","world");
@Override
protected void onDestroy() {
AsyncTaskUtil.destroy(this);
super.onDestroy();
}
package asyncTask;
public class AsyncCallSimple extends AsyncCallAbs {
private MyAsyncTask task;
public void bindTask(MyAsyncTask task){
this.task = task;
}
@Override
public void onPreCall() {
}
@Override
public Object onCall(Object[] objects) throws Exception {
return null;
}
@Override
public void publishProgress(Object... values) {
if(null != task)
task.publishProgress(values);
}
@Override
public void onProgressUpdate(Object[] values) {
}
@Override
public void onCallFinished(Object result) {
}
@Override
public void cancel(boolean mayInterruptIfRunning) {
if(null != task){
task = null;
}
}
}
最后说一下MyAsyncTask类,该类只是对原生的AsyncTask类所以一点修改,将publishProgress方法的private改成public。
public final void publishProgress(Progress... values) {
if (!isCancelled()) {
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult