您的位置:首页 > 移动开发 > Android开发

Android异步任务机制之AsycTask

2017-08-20 16:30 369 查看

AsycTask 原理分析

Android 系统中我们经常把一些耗时的操作放在线程中,例如thread AsycTask 线程池
来执行一些耗时的操作,如与服务器数据的交互都需要放在线程中处理。


1,介绍

AsyncTask是Handler与线程池的封装用来可以后台更新前台的界面的一个实现类。
通过使用线程池减少线程的不断创建和销毁性能的消耗。使用线程池可以轮番的执行。


2,方法介绍

public abstract class AsyncTask<Params, Progress, Result> {}
参数
第一个表示doInBackground方法的参数类型
第三个 doInBackground返回类型
第二个:是onProgressUpdate方法的参数类型

new AsyncTask<Void,Void,Void>(){

@Override
protected Void doInBackground(Void... params) {
return null;
}
};

@Override
protected Object doInBackground(Object[] params) {
//执行后台任务 然后处理结果

Log.e("asyncTask::", "doInBackground");
// 在这个方法中可以调用publishProgress来更新任务进度
// (publishProgress内部会调用onProgressUpdate方法)  try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}

@Override
protected void onPreExecute() {
super.onPreExecute();
Log.e("asyncTask::", "onPreExecute");

}

@Override
protected void onPostExecute(Object o) {
//后台任务后 执行此方法
super.onPostExecute(o);
Log.e("asyncTask::", "onPostExecute");

}

@Override
protected void onProgressUpdate(Object[] values) {
//若是下载任务 可以更新进度
super.onProgressUpdate(values);
Log.e("asyncTask::", "onProgressUpdate");

}

@Override
protected void onCancelled(Object o) {
super.onCancelled(o);
Log.e("asyncTask::", "onCancelled1");

}

@Override
protected void onCancelled() {
super.onCancelled();
Log.e("asyncTask::", "onCancelled2"); //先执行
}
};


以上方法中,除了doInBackground方法由AsyncTask内部线程池执行外,其余方法均在 主线程中执行。

3,使用限制

- 必须在主线程创建AsyncTack对象,因为Handler必须在主线程中被初始化。

- 执行execute()可以在非主线程中调用

4,从源码看AsyncTask到底是如何运行的首先看它的构造函数都干了些什么事

public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);  //表示已被调用
Result result = null;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//优先级
//noinspection unchecked
result = doInBackground(mParams);  //调用doInBackground()方法
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
postResult(result);
///*********  执行结果传入POSTResult();
}
return result;
}
};

WorkerRunnable是一个匿名内部类,继承Callable 实现Call()方法。。。。    Params使用的是第一参数  Result使用第三参数
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
}

最后会在线程中调用 mWorker.call() 执行doInBackground();

mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
try {
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occurred while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
} };
}


FutureTask 实际上是继承了Runnable接口

构造方法中把mWorker当参数传进FutureTask中最后会在 run方法中发现调用了mWorker.call();方法 然后会执行doinbackground();

我们在来看run方法到底是什么时候被调用的,从execute()可以找到一些线索。

@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);   //sDefaultExecutor默认的串行线程  我们可以自己创建不同类型的线程池例如并行线程
}

//并行线程
public static final Executor THREAD_POOL_EXECUTOR;

static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}

@MainThread
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
if (mStatus != Status.PENDING) {
switch (mStatus) {
case RUNNING:
throw new IllegalStateException("Cannot execute task:"
+ " the task is already running.");
case FINISHED:
throw new IllegalStateException("Cannot execute task:"
+ " the task has already been executed "
+ "(a task can be executed only once)");
}
}     //从这些判断可以看出execute()只能被执行一次不然会出错
mStatus = Status.RUNNING;

onPreExecute();   //在后台任务执行前被调用

mWorker.mParams = params;
exec.execute(mFuture);  //mFuture当做参数传入execute中
//exec 代表创建的线程池

return this;
}

////可以看到传入一个Runnaable实现类就行了
public interface Executor {

void execute(Runnable command);
}

public static final Executor SERIAL_EXECUTOR = new SerialExecutor();

private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;

public synchronized void execute(final Runnable r) {          //mFuture代表传入的Runnable实现类
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();   //调用它的run()方法   然后会在它的run()方法中 调用Call()方法
} finally {
scheduleNext();
}
scheduleNext();
}
}


“`

然后我们再来看一个开头中postResult()源码到底做了什么事

//后台线程中执行

private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}


通过Handler向主线程发送了信息。

然后看一下Handler实现类

private static class InternalHandler extends Handler {
public InternalHandler() {
super(Looper.getMainLooper());
}
因为这里需要获取的主线的的Looper所以这就解释了为什么需要在主线程中创        建AsnycTask对象了   为了sHandler将执行环境从后台线程切换到主线程(即在主    线程中执行handleMessage方法),我们必须使用主线程的Looper,
因此必须在主线程中创建sHandler。这也就解释了为什么必须在主线程中加载AsyncTask类,是为了完成sHandler这个静态成员的初始化工作。

@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
public void handleMessage(Message msg) {
AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
// There is only one result
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  asynctask