AsyncTask源码分析

Android UI是线程不安全的,如果想要在子线程很好的访问ui, 就要借助Android中的异步消息处理机制

http://blog.csdn.net/yianemail/article/details/50233373

通过Thread 执行耗时操作,通常利用Handler 发送消息给ui线程。

这种方式代码相对臃肿,并且不能对多任务执行很好的控制。

为了简化操作,Android 1.5提供了更加轻量级的AsyncTask异步工具类,使创建异步任务变得异常简单。

2,AsyncTask 的使用

看一个最典型的AsyncTask 简单使用场景

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.listenread.luhuanju.helloword;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
 
public class MainActivity  extends AppCompatActivity {
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         //AsyncTask 开始执行异步任务
         new MyAsyncTask().execute();
     }
 
     class MyAsyncTask  extends AsyncTask<Void, Void, String> {
         @Override
         protected String doInBackground(Void... params) {
             //Commen is request resurce from http and return to onPostExecute
             //模拟数据返回
             return "mStr" ;
         }
 
         @Override
         protected void onPostExecute(String s) {
             super .onPostExecute(s);
             //获取数据
         }
     }
}

3,源码解析

既然代码入口

1
new MyAsyncTask().execute();

我们就从它的构造函数分析,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
    * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
    * 方法注释就说明了必须要在ui thread 进行AsyncTask调用
    */
   public AsyncTask() {
       mWorker =  new WorkerRunnable<Params, Result>() {
           public Result call()  throws Exception {
               mTaskInvoked.set( true );
 
               Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
               //noinspection unchecked
               Result result = doInBackground(mParams);
               Binder.flushPendingCommands();
               return postResult(result);
           }
       };
 
       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 );
               }
           }
       };

来分析一下构造函数实例化的两个变量
mWorker 以及 mFuture

1
2
3
private static abstract class WorkerRunnable<Params, Result>  implements Callable<Result> {
     Params[] mParams;
}

可以看到mWorker 是实现了参数是泛型的 Callable接口,看下Callable接口的声明

1
2
3
4
5
6
7
8
9
public interface Callable<V> {
     /**
      * Computes a result, or throws an exception if unable to do so.
      *
      * @return computed result
      * @throws Exception if unable to compute a result
      */
     V call()  throws Exception;
}

只有一个返回类型为泛型的 Call() 方法。

这里介绍一下Callable 这个接口,在java中,实现多线程的方法除了Runnable之外,还有Callable,Future 以及FutureTask(没错,就是一会要分析的这货),与Runnable不同的是,这几个类型都只能在线程池当中实现。Callable 与 Runnable 最关键的异点是Callable 可以有返回值。然而Runnable 是拿不到执行的返回值的。
这也就再一次解释了

1
2
3
public interface Callable&lt;V&gt; {
     V call()  throws Exception;  //返回值泛型v
}

对比Runnable的接口声明

1
2
3
public interface Runnable {
     public void run();  //无返回值
}

再来看一下mFuture 这货,可以看到把mWorker当作参数

1
public class FutureTask<V>  implements RunnableFuture<V> {

可以看到FutureTask 实现了RunnableFuture< V>接口

1
2
3
4
5
6
7
public interface RunnableFuture<V>  extends Runnable, Future<V> {
     /**
      * Sets this Future to the result of its computation
      * unless it has been cancelled.
      */
     void run();
}

而RunnableFuture 继承了Runnable 以及Future
终于到了Future了,继续看Future 的声明

1
2
3
4
5
6
7
8
9
10
11
public interface Future<V> {
  /**
   * ...忽略方法的注释声明
   */
     boolean cancel( boolean mayInterruptIfRunning);
     boolean isCancelled();
     boolean isDone();
     V get()  throws InterruptedException, ExecutionException;
     V get( long timeout, TimeUnit unit)
         throws InterruptedException, ExecutionException, TimeoutException;
}

看到这 我们大概明白了AsyncTask的一大优势所在,没错,就是可控。
总结一下FutureTask的作用,FutureTask作为一个可管理的异步任务,使得在线程池中执行的异步任务可以被更精准的控制。

分析完构造函数中 两个实例化的变量,在继续看execute()方法

1
2
3
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
     return executeOnExecutor(sDefaultExecutor, params);
}

execute()继续调用了executeOnExecutor(sDefaultExecutor, params) ,并且传递两个参数sDefaultExecutor以及params

我们看下sDefaultExecutor

1
2
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
public static final Executor SERIAL_EXECUTOR =  new SerialExecutor();

所以我们只需要看下SerialExecutor 的实现即可;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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 的内部类,实现了Executor 接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface Executor {
 
     /**
      * Executes the given command at some time in the future.  The command
      * may execute in a new thread, in a pooled thread, or in the calling
      * thread, at the discretion of the {@code Executor} implementation.
      *
      * @param command the runnable task
      * @throws RejectedExecutionException if this task cannot be
      * accepted for execution
      * @throws NullPointerException if command is null
      */
     void execute(Runnable command);
}

我们看下这句方法的注释就能明白execute()的作用就是在线程池中分配线程执行异步任务。那么execute()方法在AsyncTask 到底执行什么任务呢?没错,就是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public synchronized void execute( final Runnable r) {
            mTasks.offer( new Runnable() {
                public void run() {
                    try {
                        r.run();
                    finally {
                        scheduleNext();
                    }
                }
            });
            if (mActive ==  null ) {
                scheduleNext();
            }
        }

我们发现了 mTasks.offer 这个方法,看下mTasks

1
final ArrayDeque<Runnable> mTasks =  new ArrayDeque<Runnable>();

简单说一下ArrayDeque

ArrayDeque是一个双端队列,它具有:

数组双端队列没有容量限制,使他们增长为必要支持使用。

不支持多线程并发访问。

它们要比堆栈Stack和LinkedList快。

看下它的offer()

1
2
3
4
5
6
7
8
9
10
11
12
/**
   * Inserts the specified element at the end of this deque.
   * 这句注释的意思就是说添加特定的元素(就是Runnable)到队尾
   * <p>This method is equivalent to {@link #offerLast}.
   *
   * @param e the element to add
   * @return <tt>true</tt> (as specified by {@link Queue#offer})
   * @throws NullPointerException if the specified element is null
   */
  public boolean offer(E e) {
      return offerLast(e);
  }

调用的 offerLast(e)

1
2
3
4
public boolean offerLast(E e) {
     addLast(e);
     return true ;
}

继续addLast(e)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    public void addLast(E e) {
        if (e ==  null )
            throw new NullPointerException( "e == null" );
        elements[tail] = e;
        if ( (tail = (tail +  1 ) &amp; (elements.length -  1 )) == head)
            doubleCapacity();
    }
 
/**
     * Double the capacity of this deque.  Call only when full, i.e.,
     * when head and tail have wrapped around to become equal.
     */
    private void doubleCapacity() {
        // assert head == tail;
        int p = head;
        int n = elements.length;
        int r = n - p;  // number of elements to the right of p
        int newCapacity = n &lt;&lt;  1 ;
        if (newCapacity &lt;  0 )
            throw new IllegalStateException( "Sorry, deque too big" );
        Object[] a =  new Object[newCapacity];
        System.arraycopy(elements, p, a,  0 , r);
        System.arraycopy(elements,  0 , a, r, p);
        elements = a;
        head =  0 ;
        tail = n;
    }

简单分析一下addLast(e) 的作用吧,如果传入参数为空,抛出异常
如果此时队列已满,就执行doubleCapacity();而这个方法就是把ArrayDeque扩容的,通过

1
2
3
4
5
6
7
8
...
  int r = n - p;  // number of elements to the right of p
  int newCapacity = n &lt;&lt;  1 ; //二进制,左移
  ...
  Object[] a =  new Object[newCapacity];
  System.arraycopy(elements, p, a,  0 , r);
  System.arraycopy(elements,  0 , a, r, p);
...

我们可知,满了就要扩容一倍的

说了这么多,我们重新回顾一下SerialExecutor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
private static class SerialExecutor  implements Executor {
         final ArrayDeque&lt;Runnable&gt; mTasks =  new ArrayDeque&lt;Runnable&gt;();
         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);
             }
         }
     }

分析一下它的执行过程
第一次运行的时候,毫无疑问,局部变量mActive为null,执行scheduleNext()方法

1
2
3
4
5
protected synchronized void scheduleNext() {
           if ((mActive = mTasks.poll()) !=  null ) {
               THREAD_POOL_EXECUTOR.execute(mActive);
           }
       }

又看到了 THREAD_POOL_EXECUTOR

1
2
3
public static final Executor THREAD_POOL_EXECUTOR
         new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
                 TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);

THREAD_POOL_EXECUTOR 也是一个线程池,通过构造函数初始化了
核心线程数,超时时长,所容纳的最大线程数,等一系类配置。在我的sdk版本好像对之前4.x做了优化,并没有固定写死,因为是这样的

1
2
3
4
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private static final int CORE_POOL_SIZE = CPU_COUNT +  1 ;
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT *  2 1 ;
private static final int KEEP_ALIVE =  1 ;

sDefaultExecutor 线程池内部维护一个任务队列(ArrayDeque),
execute()方法,将Runnable放入队尾,第一次执行 走scheduleNext(),此时 mTasks.poll() 取出队首任务,不为空则传入THREAD_POOL_EXECUTOR进行执行。

4,执行过程回顾

再来看一下 AsyncTask.execute()的执行过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@MainThread
public final AsyncTask&lt;Params, Progress, Result&gt; 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();   //熟悉这个onPreExecute()方法吗?
     mWorker.mParams = params; //外部参数赋值给mWorker局部变量
     //最主要的逻辑就在这个方法了,提交mFuture执行,封装了worker,
     exec.execute(mFuture);
     return this ;
}

mFuture 是需要mWorker 作为参数,而mWorker的执行

1
2
3
4
5
6
7
8
9
10
11
12
mWorker =  new WorkerRunnable&lt;Params, Result&gt;() {
        public Result call()  throws Exception {
            mTaskInvoked.set( true );
             //提升线程的优先级
          Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
            //noinspection unchecked
            //看到了吗?这里的doInBackground 执行的就是你外部调用的 doInBackground()的逻辑。
            Result result = doInBackground(mParams);
            Binder.flushPendingCommands();
            return postResult(result);
        }
    };

拿到结果调用postResult(result)

1
2
3
4
5
6
7
8
private Result postResult(Result result) {
     @SuppressWarnings ( "unchecked" )
     //getHandler()实际上就是 super(Looper.getMainLooper());,也就是Main 中的looper
     Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
             new AsyncTaskResult&lt;Result&gt;( this , result));
     message.sendToTarget();
     return result;
}

AsyncTaskResult就是一个简单的携带参数的对象。

看到Messager 肯定会有Handler,于是找到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private static class InternalHandler  extends Handler {
     public InternalHandler() {
         super (Looper.getMainLooper());
     }
 
     @SuppressWarnings ({ "unchecked" "RawUseOfParameterizedType" })
     @Override
     public void handleMessage(Message msg) {
         AsyncTaskResult&lt;?&gt; result = (AsyncTaskResult&lt;?&gt;) 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 ;
         }
     }
}

result.mTask.finish(result.mData[0]) 其实就是调用了AsyncTask类中的finish方法

1
2
3
4
5
6
7
8
private void finish(Result result) {
     if (isCancelled()) {
         onCancelled(result);
     else {
         onPostExecute(result);
     }
     mStatus = Status.FINISHED;
}

调用了cancel()则执行onCancelled回调;正常执行的情况下调用我们的onPostExecute(result);最后将状态置为FINISHED。

再回到mFuture

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mFuture =  new FutureTask&lt;Result&gt;(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 );
                }
            }
        };

执行 postResultIfNotInvoked(get());

1
2
3
4
5
6
private void postResultIfNotInvoked(Result result) {
     final boolean wasTaskInvoked = mTaskInvoked.get();
     if (!wasTaskInvoked) {
         postResult(result);
     }
}

根据 wasTaskInvoked状态判断是否执行postResult(result);

在mWorker 中我们已经知道 wasTaskInvoked.set(true)

所以该方法不会执行。

至此,AsyncTask源码分析完毕,相信大家对AsyncTask有了更深的理解~~~

转载请注明出处:http://blog.csdn.net/yianemail/article/details/51611326

转载请注明:Android开发中文站 » 你真的了解AsyncTask吗?AsyncTask源码分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值