AsyncTask,即异步任务,是Android给我们提供的一个处理异步任务的类.为了将Handler、静态Thread等封装为一个异步执行框架,方便调用。主要目的是为了“在其他线程中执行一个耗时操作,并随时报告执行进度给UI线程,执行完成后将结果报告给UI线程”。通过此类,可以实现UI线程和后台线程进行通讯,后台线程执行异步任务,并把结果返回给UI线程.。
我们知道,Android中只有主线程才能进行对UI的更新操作,其他线程是不能直接操作UI的。但总不能把所有的任务都放在主线程中进行实现,所以就出现了AsyncTask。
在AsyncTask中可以执行一些耗时操作,网络请求,可以很好的避免ANR错误。反之全部放到主线程去执行,就可能会造成后面任务的阻塞。当阻塞时间太长的时候,就会抛出Application Not Responsed(ANR)错误.所以我们需要将这些耗时操作放在非主线程中去执行.这样既避免了Android的单线程模型,又避免了ANR.
源码详细:https://blog.csdn.net/m0_37700275/article/details/83546140
继承AsyncTask的类指定了三个泛型参数:
AsyncTask中有三个方法:
class MyAsyncTask extends AsyncTask {
@Override
protected void onPreExecute() {
super.onPreExecute();
Log.i(TAG, "onPreExecute...(开始执行后台任务之前)");
}
@Override
protected void onPostExecute(Integer i) {
super.onPostExecute(i);
Log.i("TAG", "onPostExecute...(开始执行后台任务之后)");
}
@Override
protected Integer doInBackground(Integer... params) {
Log.i(TAG, "doInBackground...(开始执行后台任务)");
return 0;
}
}
开始执行异步方法:
new MyAsyncTask().execute();
我们先从他Execute方法,其中有一个ExecuteOnExcuteor的方法,通过Status.Pending来判断当前的任务状态。如果为正在执行这个任务,或者是已经完成任务的情况下,就会出现异常,只有是未完成的情况下,开始执行OnPerExecute()的方法。以及把我们的params赋值给mworker.mparams(),并执行execute方法,把mFurture方法传过去!
public final AsyncTask 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)");
}
}
mStatus = Status.RUNNING;
onPreExecute();
mWorker.mParams = params;
exec.execute(mFuture);
return this;
}
AsyncTask中有两个线程池,和一个Handler,其中有一个SerialExector()的方法是用来任务排队,THREAD_POLL_EXECUTOR的方法是用来真正的执行任务!
那么接下来就用SerialExector()的方法来看看其中是如何排队的?那么这里用了锁来限制,首先它实现了ExeCutor的接口,实现了接口中的Call()方法。
mWorker = new WorkerRunnable() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Result result = null;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
postResult(result);
}
return result;
}
};
接下来在SerialExector类中实现runnable方法,用一个r.run(),间接的调用了Call方法中的DoInBackground(),再调用其中的oScheduleNext()方法,判断当前任务是否为空,不为空则执行THREAD_POLL_EXECUTOR方法,处理任务!
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
private static class SerialExecutor implements Executor {
final ArrayDeque mTasks = new ArrayDeque();
Runnable mActive;
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
处理完后,就要用到Handler来将线程环境转换为主线程也就是要执行onPostExecute()方法
1.AsyncTask:使用的优点: 简单,快捷、过程可控.
2.Handler:
源码了解:https://blog.csdn.net/LoverLeslie/article/details/85267367
1.AsyncTask:
解决办法:将AsyncTask设置为静态内部类、在Activity的onDestory()方法中finish掉 (AsyncTask.cancle() )、将内部改为持有外部类的弱引用。
2.Handler:
原因:handler如果是是非静态内部类 ,那么就会引用外部类的匿名引用,导致Activity无法释放
解决办法:将Handler设置为静态内部类、在Activity的onDestory()方法中remove掉( handler.removeCallback() )、将内部改为持有外部类的弱引用。