AsyncTask的使用
/**
* 避免内存泄露,用弱引用包裹,加静态内部类的方式处理
*/
//输入的参数 String 执行进度 Integer 返回的结果 String
// a. Params:开始异步任务执行时传入的参数类型,对应excute()中传递的参数
// b. Progress:异步任务执行过程中,返回下载进度值的类型
// c. Result:异步任务执行完成后,返回的结果类型,与doInBackground()的返回值类型保持一致
static class MyAsynTask extends AsyncTask<String,Integer,String>{
private WeakReference<ProgressBar> progressBarWeakReference;
private WeakReference<TextView> textViewWeakReference;
public MyAsynTask(ProgressBar progressBar,TextView textView){
progressBarWeakReference = new WeakReference<>(progressBar);
textViewWeakReference = new WeakReference<>(textView);
}
@Override
protected void onPreExecute() {
TextView textView = textViewWeakReference.get();
textView.setText("加载中");
}
@Override
protected String doInBackground(String... strings) {
try {
int count = 0;
while (count <= 100){
Thread.sleep(1000);
count += 1;
publishProgress(count);
}
}catch (Exception e){
e.printStackTrace();
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
ProgressBar progressBar = progressBarWeakReference.get();
progressBar.setProgress(values[0]);
TextView textView = textViewWeakReference.get();
textView.setText("Loading.."+ values[0] + "%");
}
@Override
protected void onPostExecute(String s) {
TextView textView = textViewWeakReference.get();
textView.setText("加载完毕");
}
@Override
protected void onCancelled() {
TextView textView = textViewWeakReference.get();
textView.setText("已取消");
ProgressBar progressBar = progressBarWeakReference.get();
progressBar.setProgress(0);
}
}
/**
* 在onDestroy的时候取消任务
*/
@Override
protected void onDestroy() {
super.onDestroy();
mMyAsynTask.cancel(true);
}
源码分析
mMyAsynTask.execute();
调用execute启动任务。
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
从上面可以知道有一个@MainThread注解,表面该方法只能在主线程执行。
@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)");
}
}
mStatus = Status.RUNNING;
onPreExecute();
mWorker.mParams = params;
exec.execute(mFuture);
return this;
}
@UnsupportedAppUsage
private volatile Status mStatus = Status.PENDING;
public enum Status {
/**
* Indicates that the task has not been executed yet.
*/
PENDING,
/**
* Indicates that the task is running.
*/
RUNNING,
/**
* Indicates that {@link AsyncTask#onPostExecute} has finished.
*/
FINISHED,
}
首先判断状态,总共有三种状态,分别为PENDING,RUNNING,FINISHED。默认的为PENDING,当执行executeOnExecutor方法时,将状态改为RUNNING。
这也是一个==AsyncTask对象不能被多次执行的原因。== 因为执行executeOnExecutor()时,只要初始状态不是PENDING就会报错。
最后执行exec.execute(mFuture)。其中exec是sDefaultExecutor,下面来看一下sDefaultExecutor。
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) {
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);
}
}
}
SerialExecutor 内部维持了一个队列,通过锁使得该队列保证AsyncTask中的任务是串行执行的,即多个任务需要一个个加到该队列中。加入的这个任务就是mFuture。
exec.execute(mFuture)实际上是先向ArrayDeque这个队列中加入mFuture这个任务。然后调用scheduleNext(),调用THREAD_POOL_EXECUTOR执行队列头部的任务。
mFuture = new FutureTask<Result>(mWorker)
在加入时会执行r.run(),即执行mFuture.run().
public void run() {
if (state != NEW ||
!U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();//1
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}
//构造函数
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
}
由构造函数我们可以知道,传入的callable就是mWorker。
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);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
postResult(result);
}
return result;
}
};
在mFuture.run()的run()方法中,会执行//1处,即执行mWorker.call()。在call方法中,先执行完doInBackground()方法,又执行postResult()方法。
THREAD_POOL_EXECUTOR实际是个线程池,开启了一定数量的核心线程和工作线程。然后调用线程池的execute()方法。执行具体的耗时任务,即开头构造函数中mWorker中call()方法的内容。由此可知,真正执行耗时任务的是THREAD_POOL_EXECUTOR。SerialExecutor只是将任务加入其中。
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
然后通过Handler将耗时操作返回的结果放到主线程。
private static Handler getMainHandler() {
synchronized (AsyncTask.class) {
if (sHandler == null) {
sHandler = new InternalHandler(Looper.getMainLooper());
}
return sHandler;
}
}
private static class InternalHandler extends Handler {
public InternalHandler(Looper looper) {
super(looper);
}
@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;
}
}
}
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
? getMainHandler()
: new Handler(callbackLooper);
private Handler getHandler() {
return mHandler;
}
这里使用sHandler对象发出了一条消息,消息中携带了MESSAGE_POST_RESULT常量和一个表示任务执行结果的AsyncTaskResult对象。这里对消息的类型进行了判断,如果这是一条MESSAGE_POST_RESULT消息,就会去执行finish()方法,如果这是一条MESSAGE_POST_PROGRESS消息,就会去执行onProgressUpdate()方法。
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
可以看到,如果当前任务被取消掉了,就会调用onCancelled()方法,如果没有被取消,则调用onPostExecute()方法,这样当前任务的执行就全部结束了。
然后将状态变成FINISHED。
在3.0以前,最大支持128个线程的并发,10个任务的等待,同时执行138个任务是没有问题的;而超过138会马上出现java.util.concurrent.RejectedExecutionException。在3.0以后,无论有多少任务,都会在其内部单线程执行;
如果想让AsyncTask在3.0以上的系统中并行: 调用AsyncTask的executeOnExecutor方法而不是execute方法
btn_a.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new MyTask("AsyncTask#1").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");
new MyTask("AsyncTask#2").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");
new MyTask("AsyncTask#3").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");
new MyTask("AsyncTask#4").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");
new MyTask("AsyncTask#5").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");
}
});
2020-10-07 14:32:59.341 29216-29216/com.example.asyntask E/AsyncTask: AsyncTask#2execute finish at 2020-10-07 14:32:59
2020-10-07 14:32:59.342 29216-29216/com.example.asyntask E/AsyncTask: AsyncTask#1execute finish at 2020-10-07 14:32:59
2020-10-07 14:32:59.343 29216-29216/com.example.asyntask E/AsyncTask: AsyncTask#4execute finish at 2020-10-07 14:32:59
2020-10-07 14:32:59.343 29216-29216/com.example.asyntask E/AsyncTask: AsyncTask#3execute finish at 2020-10-07 14:32:59
2020-10-07 14:32:59.343 29216-29216/com.example.asyntask E/AsyncTask: AsyncTask#5execute finish at 2020-10-07 14:32:59
网友评论