AsyncTask 源码分析及仿 AsyncTask 异步任务举例

458 阅读43分钟

参考:

Android 从零开始打造异步处理框架

详解Android中AsyncTask的使用

Android AsyncTask 源码解析

AsyncTask源码分析及仿AsyncTask异步任务举例

最近研究研究网络框架,不打算研究那些虚浮的新技术。

第一部分:AsyncTask简单使用方式:

一、AsyncTask的使用方式(Demo来自鸿洋的博客)

  1. public class Main2Activity extends Activity {  
  2.     private static final String TAG =  "Main2Activity";  
  3.     private ProgressDialog mDialog;  
  4.     private TextView mTextView;  
  5.     @Override  
  6.     protected void onCreate(Bundle savedInstanceState) {  
  7.         super.onCreate(savedInstanceState);  
  8.         setContentView(R.layout.activity_main2);  
  9.         mTextView = (TextView) findViewById(R.id.id_tv);  
  10.   
  11.         mDialog = new ProgressDialog(this);  
  12.         mDialog.setMax(100);  
  13.         mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);  
  14.         mDialog.setCancelable(false);  
  15.   
  16.         new MyAsyncTask().execute();  
  17.     }  
  18.   
  19.     private class MyAsyncTask extends AsyncTask<Void, Integer, Void>  
  20.     {  
  21.   
  22.         @Override  
  23.         protected void onPreExecute()  
  24.         {  
  25.             mDialog.show();  
  26.             Log.e(TAG, Thread.currentThread().getName() + " onPreExecute ");  
  27.         }  
  28.   
  29.         @Override  
  30.         protected Void doInBackground(Void... params)  
  31.         {  
  32.   
  33.             // 模拟数据的加载,耗时的任务  
  34.             for (int i = 0; i <  100; i++)  
  35.             {  
  36.                 try  
  37.                 {  
  38.                     Thread.sleep(80);  
  39.                 } catch (InterruptedException e)  
  40.                 {  
  41.                     e.printStackTrace();  
  42.                 }  
  43.                 publishProgress(i);  
  44.             }  
  45.   
  46.             Log.e(TAG, Thread.currentThread().getName() + " doInBackground ");  
  47.             return null;  
  48.         }  
  49.   
  50.         @Override  
  51.         protected void onProgressUpdate(Integer... values)  
  52.         {  
  53.             mDialog.setProgress(values[0]);  
  54.             Log.e(TAG, Thread.currentThread().getName() + " onProgressUpdate ");  
  55.         }  
  56.   
  57.         @Override  
  58.         protected void onPostExecute(Void result)  
  59.         {  
  60.             // 进行数据加载完成后的UI操作  
  61.             mDialog.dismiss();  
  62.             mTextView.setText("LOAD DATA SUCCESS ");  
  63.             Log.e(TAG, Thread.currentThread().getName() + " onPostExecute ");  
  64.         }  
  65.     }  
  66. }  
public class Main2Activity extends Activity {
    private static final String TAG = "Main2Activity";
    private ProgressDialog mDialog;
    private TextView mTextView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        mTextView = (TextView) findViewById(R.id.id_tv);

        mDialog = new ProgressDialog(this);
        mDialog.setMax(100);
        mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        mDialog.setCancelable(false);

        new MyAsyncTask().execute();
    }

    private class MyAsyncTask extends AsyncTask<Void, Integer, Void>
    {

        @Override
        protected void onPreExecute()
        {
            mDialog.show();
            Log.e(TAG, Thread.currentThread().getName() + " onPreExecute ");
        }

        @Override
        protected Void doInBackground(Void... params)
        {

            // 模拟数据的加载,耗时的任务
            for (int i = 0; i < 100; i++)
            {
                try
                {
                    Thread.sleep(80);
                } catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
                publishProgress(i);
            }

            Log.e(TAG, Thread.currentThread().getName() + " doInBackground ");
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values)
        {
            mDialog.setProgress(values[0]);
            Log.e(TAG, Thread.currentThread().getName() + " onProgressUpdate ");
        }

        @Override
        protected void onPostExecute(Void result)
        {
            // 进行数据加载完成后的UI操作
            mDialog.dismiss();
            mTextView.setText("LOAD DATA SUCCESS ");
            Log.e(TAG, Thread.currentThread().getName() + " onPostExecute ");
        }
    }
}

二、效果图如下:

三、Log日志打印如下:

  1. 12-22 10:29:07.287  12897-12897/com.simple.simpledemo E/Main2Activity: main onPreExecute   
  2. 12-22 10:29:07.397  12897-12897/com.simple.simpledemo E/Main2Activity: main onProgressUpdate   
  3. ...此处省略(共100个onProgressUpdate)...  
  4. 12-22 10:29:15.297  12897-12897/com.simple.simpledemo E/Main2Activity: main onProgressUpdate   
  5. 12-22 10:29:15.377  12897-28721/com.simple.simpledemo E/Main2Activity: AsyncTask #5 doInBackground   
  6. 12-22 10:29:15.377  12897-12897/com.simple.simpledemo E/Main2Activity: main onProgressUpdate   
  7. 12-22 10:29:15.387  12897-12897/com.simple.simpledemo E/Main2Activity: main onPostExecute   
12-22 10:29:07.287 12897-12897/com.simple.simpledemo E/Main2Activity: main onPreExecute 
12-22 10:29:07.397 12897-12897/com.simple.simpledemo E/Main2Activity: main onProgressUpdate 
...此处省略(共100个onProgressUpdate)...
12-22 10:29:15.297 12897-12897/com.simple.simpledemo E/Main2Activity: main onProgressUpdate 
12-22 10:29:15.377 12897-28721/com.simple.simpledemo E/Main2Activity: AsyncTask #5 doInBackground 
12-22 10:29:15.377 12897-12897/com.simple.simpledemo E/Main2Activity: main onProgressUpdate 
12-22 10:29:15.387 12897-12897/com.simple.simpledemo E/Main2Activity: main onPostExecute 

第二部分、AsyncTask源码分析:

知道如何使用后,看看使用AsyncTask的代码;

  1. private class MyAsyncTask extends AsyncTask<Void, Integer, Void>  
  2.     {  
  3.   
  4.         @Override  
  5.         protected void onPreExecute()  
  6.         {  
  7.             ......之前  
  8.         }  
  9.   
  10.         @Override  
  11.         protected Void doInBackground(Void... params)  
  12.         {  
  13.   
  14.             ......处理  
  15.             return null;  
  16.         }  
  17.   
  18.         @Override  
  19.         protected void onProgressUpdate(Integer... values)  
  20.         {  
  21.             ......进度  
  22.         }  
  23.   
  24.         @Override  
  25.         protected void onPostExecute(Void result)  
  26.         {  
  27.             ......之后  
  28.         }  
  29.     }  
private class MyAsyncTask extends AsyncTask<Void, Integer, Void>
    {

        @Override
        protected void onPreExecute()
        {
            ......之前
        }

        @Override
        protected Void doInBackground(Void... params)
        {

            ......处理
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values)
        {
            ......进度
        }

        @Override
        protected void onPostExecute(Void result)
        {
            ......之后
        }
    }
复写了四个方法。一个个来。我们反向推导AsyncTask的源码。

1.先看调用方法:new MyAsyncTask().execute(),再看哪个地方调用了这四个复写的方法。

(一)AsyncTask初始化

——————————初始化开始——————————

先看构造方法吧:

  1. public AsyncTask() {  
  2.         mWorker = new WorkerRunnable<Params, Result>() {  
  3.             public Result call() throws Exception {  
  4.                 mTaskInvoked.set(true);  
  5.   
  6.                 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);  
  7.                 //noinspection unchecked  
  8.                 Result result = doInBackground(mParams);  
  9.                 Binder.flushPendingCommands();  
  10.                 return postResult(result);  
  11.             }  
  12.         };  
  13.   
  14.         mFuture = new FutureTask<Result>(mWorker) {  
  15.             @Override  
  16.             protected void done() {  
  17.                 try {  
  18.                     postResultIfNotInvoked(get());  
  19.                 } catch (InterruptedException e) {  
  20.                     android.util.Log.w(LOG_TAG, e);  
  21.                 } catch (ExecutionException e) {  
  22.                     throw new RuntimeException( "An error occurred while executing doInBackground()",  
  23.                             e.getCause());  
  24.                 } catch (CancellationException e) {  
  25.                     postResultIfNotInvoked(null);  
  26.                 }  
  27.             }  
  28.         };  
  29.     }  
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

mWorker、mFuture两个对象是什么?

——————————扫盲分割线开始——————————

一个比较尴尬的事,一开始不知道Callable和FutrueTask。因此一开始一直也没看懂。

OK,知道哪不懂,才能去懂。简单讲讲我的这个盲区:

Callable:

是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其他线程执行的任务。

Runnable和Callable的区别是:

(1)Callable规定的方法是call(),Runnable规定的方法是run()。
(2)Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。
(3)call方法可以抛出异常,run方法不可以。
(4)运行Callable任务可以拿到一个Future对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。

简单理解为runnable类似就好。

FutureTask:

FutureTask实际上是一个任务的操作类,它并不启动新线程,只是在自己所在线程上操作,任务的具体实现是构造FutureTask时提供的。

FutureTask执行Callable任务(类似Thread执行runnable任务),执行完会调用done方法。

——————————扫盲分割线结束——————————

mWorker

  1. mWorker = new WorkerRunnable<Params, Result>() {  
  2.             public Result call() throws Exception {  
  3.                 mTaskInvoked.set(true);  
  4.   
  5.                 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);  
  6.                 //noinspection unchecked  
  7.                 Result result = doInBackground(mParams);  
  8.                 Binder.flushPendingCommands();  
  9.                 return postResult(result);  
  10.             }  
  11.         };  
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);
            }
        };

doInBackground:方法在任务内执行,类似runnalbe的run方法。执行完call方法,会调用postResult方法。

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

先暂时简单描述为:发送消息通知给主UI线程。执行handler的主UI操作。

暂时先不讲handler调用,放到后面讲。这儿先把初始化讲完。

mFuture:

复写了done方法,意味着执行完任务mWorker后,会调用done方法。

  1. mFuture = new FutureTask<Result>(mWorker) {  
  2.             @Override  
  3.             protected void done() {  
  4.                 try {  
  5.                     postResultIfNotInvoked(get());  
  6.                 } catch (InterruptedException e) {  
  7.                     android.util.Log.w(LOG_TAG, e);  
  8.                 } catch (ExecutionException e) {  
  9.                     throw new RuntimeException( "An error occurred while executing doInBackground()",  
  10.                             e.getCause());  
  11.                 } catch (CancellationException e) {  
  12.                     postResultIfNotInvoked(null);  
  13.                 }  
  14.             }  
  15.         };  
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);
                }
            }
        };
postResultIfNotInvoked(get()):
  1. private void postResultIfNotInvoked(Result result) {  
  2.         final boolean wasTaskInvoked = mTaskInvoked.get();  
  3.         if (!wasTaskInvoked) {  
  4.             postResult(result);  
  5.         }  
  6.     }  
private void postResultIfNotInvoked(Result result) {
        final boolean wasTaskInvoked = mTaskInvoked.get();
        if (!wasTaskInvoked) {
            postResult(result);
        }
    }

第2行final boolean wasTaskInvoked = mTaskInvoked.get();mTaskInvoked对象取值,这个值好像在哪看到被赋值了。

原来在mworker对象初始化的时候设置为true了:mTaskInvoked.set(true);

也就是说如果mWorker成功初始化,则接下来的代码if(!wasTaskInvoked){... }根本不会执行括号内操作。

MyAsyncTask().execute()构造方法初始化讲完了。然后讲讲执行。

——————————初始化结束——————————

(二)AsyncTask执行

——————————执行开始———————————

MyAsyncTask().execute():

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

executeOnExecutor:

  1. public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,  
  2.             Params... params) {  
  3.         if (mStatus != Status.PENDING) {  
  4.             switch (mStatus) {  
  5.                 case RUNNING:  
  6.                     throw new IllegalStateException( "Cannot execute task:"  
  7.                             + " the task is already running.");  
  8.                 case FINISHED:  
  9.                     throw new IllegalStateException( "Cannot execute task:"  
  10.                             + " the task has already been executed "  
  11.                             + "(a task can be executed only once)");  
  12.             }  
  13.         }  
  14.   
  15.         mStatus = Status.RUNNING;  
  16.   
  17.         onPreExecute();  
  18.   
  19.         mWorker.mParams = params;  
  20.         exec.execute(mFuture);  
  21.   
  22.         return this;  
  23.     }  
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;
    }
异常检查:根据几种状态判断。默认状态是Pending,待定状态。如下。
  1. public enum Status {  
  2.         /** 
  3.          * Indicates that the task has not been executed yet. 
  4.          */  
  5.         PENDING,  
  6.         /** 
  7.          * Indicates that the task is running. 
  8.          */  
  9.         RUNNING,  
  10.         /** 
  11.          * Indicates that {@link AsyncTask#onPostExecute} has finished. 
  12.          */  
  13.         FINISHED,  
  14.     }  
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,
    }

判断不是Running,Finished状态后,

1.执行mStatus = Status.RUNNING:改变状态为Running。

2.onPreExecute():这个方法眼熟么?最开始的Demo中使Dialog显示的方法就在这儿使用。

3.mWorker.mParams = params:这个params是什么?new MyAsyncTask().execute();我们并没有传递任何参数过来。over,下一个。

4.exec.execute(mFuture):exec对象是什么?

  1. executeOnExecutor(sDefaultExecutor, params)  
executeOnExecutor(sDefaultExecutor, params)

是这个sDefaultExecutor,这个又是什么?

  1. private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;  
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
这个初始化的时候就是另一个对象:
  1. public static final Executor SERIAL_EXECUTOR = new SerialExecutor();  
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
知道这个对象,然后看看exec.execute(mFuture)调用的方法execute。

  1. public synchronized void execute(final Runnable r) {  
  2.             mTasks.offer(new Runnable() {  
  3.                 public void run() {  
  4.                     try {  
  5.                         r.run();  
  6.                     } finally {  
  7.                         scheduleNext();  
  8.                     }  
  9.                 }  
  10.             });  
  11.             if (mActive == null) {  
  12.                 scheduleNext();  
  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队列中插入一条Runnable对象(mTask对象final ArrayDeque<Runnable> mTasks)。并复写了runnable对象的run方法。成功插入后下面有一个判断if (mActive == null) 执行一个scheduleNext()方法。如下图:


分几种情况:

1)首次插入数据时,mActive默认值为空,必然立即执行scheduleNext()(代码如下);

2)再插入数据时,mActive则可能不为空,可能不会立即scheduleNext();

3)过程中:有某一条runnable任务被执行的时候,调用其自身的run方法。尝试执行mFuture的run方法r.run()后,会立刻执行scheduleNext();同理,就是说最后一条runnable任务执行的时候,会调用scheduleNext()中的方法,尝试从mTasks队列取出runnable任务,如果mTasks队列中还有就会被取出,否则,则结束。

注意:mFuture还记得么?初始化的两个对象中的第二个FutureTask对象。插入后到上面的第10行代码为止,这个被插入队列的runnable对象还被调用。因此一开始并不会执行run()方法里面的东西。

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

mActive从队列mTasks中取出一条runnable对象(FutureTask对象mFuture),通过线程池执行。

注意:线程池有约束最大的大小,而mTasks队列没有大小约束,因此,可以无限制插入数据,但是同一时间最大能执行的线程数是固定的。见源码:

  1. private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();  
  2.     private static final int CORE_POOL_SIZE = CPU_COUNT +  1;  
  3.     private static final int MAXIMUM_POOL_SIZE = CPU_COUNT *  2 + 1;  
  4.     private static final int KEEP_ALIVE =  1;  
  5.   
  6.     private static final ThreadFactory sThreadFactory =  new ThreadFactory() {  
  7.         private final AtomicInteger mCount = new AtomicInteger( 1);  
  8.   
  9.         public Thread newThread(Runnable r) {  
  10.             return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());  
  11.         }  
  12.     };  
  13.   
  14.     private static final BlockingQueue<Runnable> sPoolWorkQueue =  
  15.             new LinkedBlockingQueue<Runnable>(128);  
  16.   
  17.     /** 
  18.      * An {@link Executor} that can be used to execute tasks in parallel. 
  19.      */  
  20.     public static final Executor THREAD_POOL_EXECUTOR  
  21.             = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,  
  22.                     TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);  
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;

    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

        public Thread newThread(Runnable r) {
            return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
        }
    };

    private static final BlockingQueue<Runnable> sPoolWorkQueue =
            new LinkedBlockingQueue<Runnable>(128);

    /**
     * An {@link Executor} that can be used to execute tasks in parallel.
     */
    public static final Executor THREAD_POOL_EXECUTOR
            = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
                    TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);

——————————执行结束———————————

(三)与主UI线程交互

执行结束之后,postResult发送消息MESSAGE_POST_RESULT给getHandler()方法的Handler。

  1. private Result postResult(Result result) {  
  2.         @SuppressWarnings("unchecked")  
  3.         Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,  
  4.                 new AsyncTaskResult<Result>(this, result));  
  5.         message.sendToTarget();  
  6.         return result;  
  7.     }  
private Result postResult(Result result) {
        @SuppressWarnings("unchecked")
        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
                new AsyncTaskResult<Result>(this, result));
        message.sendToTarget();
        return result;
    }
很明显是一个单例模式的Handler写法,看看。

  1. private static InternalHandler sHandler;  
private static InternalHandler sHandler;

InternalHandler

这个Handler看看是什么?

  1. private static Handler getHandler() {  
  2.         synchronized (AsyncTask.class) {  
  3.             if (sHandler == null) {  
  4.                 sHandler = new InternalHandler();  
  5.             }  
  6.             return sHandler;  
  7.         }  
  8.     }  
private static Handler getHandler() {
        synchronized (AsyncTask.class) {
            if (sHandler == null) {
                sHandler = new InternalHandler();
            }
            return sHandler;
        }
    }
看看InternalHandler构造方法:

  1. private static class InternalHandler extends Handler {  
  2.         public InternalHandler() {  
  3.             super(Looper.getMainLooper());  
  4.         }  
  5.   
  6.         @SuppressWarnings({"unchecked""RawUseOfParameterizedType"})  
  7.         @Override  
  8.         public void handleMessage(Message msg) {  
  9.             AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;  
  10.             switch (msg.what) {  
  11.                 case MESSAGE_POST_RESULT:  
  12.                     // There is only one result  
  13.                     result.mTask.finish(result.mData[0]);  
  14.                     break;  
  15.                 case MESSAGE_POST_PROGRESS:  
  16.                     result.mTask.onProgressUpdate(result.mData);  
  17.                     break;  
  18.             }  
  19.         }  
  20.     }  
private static class InternalHandler extends Handler {
        public InternalHandler() {
            super(Looper.getMainLooper());
        }

        @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;
            }
        }
    }

Looper.getMainLooper()获取了主UI线程的handler对象!非常好。当获得消息MESSAGE_POST_RESULT之后,执行result.mTask.finish(result.mData[0])方法。这个result对象是什么?回到发消息的postresult方法里面看下,发现getHandler().obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result)),这个result对象就是new AsyncTaskResult<Result>(this, result),result原来是AsyncTask的静态内部类AsyncTaskResult的mTask(AsyncTask自身)的finish方法。说白了就是AsyncTask自己的finish方法:(后面的Demo中会解释为什么这么传递数据)

  1. private void finish(Result result) {  
  2.         if (isCancelled()) {  
  3.             onCancelled(result);  
  4.         } else {  
  5.             onPostExecute(result);  
  6.         }  
  7.         mStatus = Status.FINISHED;  
  8.     }  
private void finish(Result result) {
        if (isCancelled()) {
            onCancelled(result);
        } else {
            onPostExecute(result);
        }
        mStatus = Status.FINISHED;
    }
正常的话执行onPostExecute方法。这个方法就是执行完成后的对主UI线程的修改方法。

貌似漏了两个方法:publishProgress(i)这个方法在子线程中发送消息MESSAGE_POST_PROGRESS给主UI线程。

  1. getHandler().obtainMessage(MESSAGE_POST_PROGRESS,  
  2.                     new AsyncTaskResult<Progress>(this, values)).sendToTarget();  
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
                    new AsyncTaskResult<Progress>(this, values)).sendToTarget();
onProgressUpdate在handler的构造方法中执行如下
  1. case MESSAGE_POST_PROGRESS:  
  2.                     result.mTask.onProgressUpdate(result.mData);  
  3.                     break;  
case MESSAGE_POST_PROGRESS:
                    result.mTask.onProgressUpdate(result.mData);
                    break;

第三部分、仿AsyncTask异步任务举例

(一)一个简单的异步任务

分析:既然是异步任务,那么开启新线程是有必要的。要求要有任务开始前onStart(),子线程onOoInBackground(),任务开始后onResult(T t)。

先写一个类继承自Thread类。复写其中的run方法。写三个抽象方法。

  1. public abstract class ThreadTask<T> extends Thread{  
  2.   
  3.     private Handler handler;  
  4.   
  5.     public ThreadTask(){  
  6.         handler = new Handler(){  
  7.             @Override  
  8.             public void handleMessage(Message msg) {  
  9.                 super.handleMessage(msg);  
  10.                 onResult((T)msg.obj);  
  11.             }  
  12.         };  
  13.     }  
  14.   
  15.     @Override  
  16.     public void run() {  
  17.         super.run();  
  18.         Message message = Message.obtain();  
  19.         message.obj = onOoInBackground();  
  20.         handler.sendMessage(message);  
  21.     }  
  22.     /** 
  23.      * 任务开始之前 
  24.      * */  
  25.     public abstract void onStart();  
  26.     /** 
  27.      * 子线程中调用,运行在子线程 
  28.      * */  
  29.     public abstract T onOoInBackground();  
  30.     /** 
  31.      * 子线程返回的结果,运行在主线程 
  32.      * */  
  33.     public abstract void onResult(T t);  
  34.   
  35.     public void execute(){  
  36.         onStart();  
  37.         start();  
  38.     }  
  39. }  
public abstract class ThreadTask<T> extends Thread{

    private Handler handler;

    public ThreadTask(){
        handler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                onResult((T)msg.obj);
            }
        };
    }

    @Override
    public void run() {
        super.run();
        Message message = Message.obtain();
        message.obj = onOoInBackground();
        handler.sendMessage(message);
    }
    /**
     * 任务开始之前
     * */
    public abstract void onStart();
    /**
     * 子线程中调用,运行在子线程
     * */
    public abstract T onOoInBackground();
    /**
     * 子线程返回的结果,运行在主线程
     * */
    public abstract void onResult(T t);

    public void execute(){
        onStart();
        start();
    }
}
该Thread继承类执行通过execute方法,先执行onStart()方法。再执行start()方法,执行内部run()方法。

在run方法内部,先执行耗时操作onOoInBackground,执行完之后再通过handler执行通知UI线程已经执行完了,handler接收到消息,执行onResult方法。

使用举例代码,在主方法里面通过如下方式使用:

  1. new ThreadTask<String>(){  
  2.             @Override  
  3.             public void onStart() {  
  4.                 Log.d("ThreadTask","我是加载动画");  
  5.             }  
  6.   
  7.             @Override  
  8.             public String onOoInBackground() {  
  9.                 try {  
  10.                     Thread.sleep(3000);  
  11.                 } catch (InterruptedException e) {  
  12.                     e.printStackTrace();  
  13.                 }  
  14.                 return "结果返回";  
  15.             }  
  16.   
  17.             @Override  
  18.             public void onResult(String s) {  
  19.                 Log.d("ThreadTask","结果"+s);  
  20.                 my_text.setText("结果"+s);  
  21.             }  
  22.         }.execute();  
new ThreadTask<String>(){
            @Override
            public void onStart() {
                Log.d("ThreadTask","我是加载动画");
            }

            @Override
            public String onOoInBackground() {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return "结果返回";
            }

            @Override
            public void onResult(String s) {
                Log.d("ThreadTask","结果"+s);
                my_text.setText("结果"+s);
            }
        }.execute();
打个Log日志吧,不发效果图了:
  1. 12-22 18:33:44.088  6407-6407/com.simple.simpledemo D/ThreadTask: 我是加载动画  
  2. 12-22 18:33:47.088  6407-6951/com.simple.simpledemo D/ThreadTask: 我是执行过程  
  3. 12-22 18:33:47.088  6407-6407/com.simple.simpledemo D/ThreadTask: 结果结果返回  
12-22 18:33:44.088 6407-6407/com.simple.simpledemo D/ThreadTask: 我是加载动画
12-22 18:33:47.088 6407-6951/com.simple.simpledemo D/ThreadTask: 我是执行过程
12-22 18:33:47.088 6407-6407/com.simple.simpledemo D/ThreadTask: 结果结果返回

逻辑上是否感受到和AsyncTask相似?比如onPreExecute和我们的onStart,doInBackground和我们的doInBackground,onPostExecute和我们的onResult。当然,看上去还有不小的差异。有差异证明我们的异步还有很大的进步空间。大的方向已经ok了。

(二)单例优化handler后的异步任务

分析:回到AsyncTask方法,发现它用了单例。我的第一版异步也应该用上单例才对,否则,每次都要new一个handler对象。

为了后续的区别,验证一下先:把handler打印出来:

  1. public ThreadTask(){  
  2.         handler = new Handler(){  
  3.             @Override  
  4.             public void handleMessage(Message msg) {  
  5.                 super.handleMessage(msg);  
  6.                 onResult((T)msg.obj);  
  7.             }  
  8.         };  
  9.         Log.d("InternalHandler",handler.toString());  
  10.     }  
public ThreadTask(){
        handler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                onResult((T)msg.obj);
            }
        };
        Log.d("InternalHandler",handler.toString());
    }
查看一下Log日志:点击两次,发现两个handler对象不同。
  1. 12-22 19:06:11.958  5397-5397/com.simple.simpledemo D/InternalHandler: Handler (com.simple.simpledemo.ThreadTask$1) { 42456248}  
  2. 12-22 19:06:11.968  5397-5397/com.simple.simpledemo D/ThreadTask: 我是加载动画  
  3. 12-22 19:06:15.008  5397-5397/com.simple.simpledemo D/ThreadTask: 结果结果返回  
  4. 12-22 19:06:16.878  5397-5397/com.simple.simpledemo D/InternalHandler: Handler (com.simple.simpledemo.ThreadTask$1) {42456e98}  
  5. 12-22 19:06:16.878  5397-5397/com.simple.simpledemo D/ThreadTask: 我是加载动画  
  6. 12-22 19:06:19.918  5397-5397/com.simple.simpledemo D/ThreadTask: 结果结果返回  
12-22 19:06:11.958 5397-5397/com.simple.simpledemo D/InternalHandler: Handler (com.simple.simpledemo.ThreadTask$1) {42456248}
12-22 19:06:11.968 5397-5397/com.simple.simpledemo D/ThreadTask: 我是加载动画
12-22 19:06:15.008 5397-5397/com.simple.simpledemo D/ThreadTask: 结果结果返回
12-22 19:06:16.878 5397-5397/com.simple.simpledemo D/InternalHandler: Handler (com.simple.simpledemo.ThreadTask$1) {42456e98}
12-22 19:06:16.878 5397-5397/com.simple.simpledemo D/ThreadTask: 我是加载动画
12-22 19:06:19.918 5397-5397/com.simple.simpledemo D/ThreadTask: 结果结果返回

先写一个最简单的单例模式:

  1. private static class InternalHandler extends Handler {  
  2.         private static InternalHandler handler;  
  3.   
  4.         private InternalHandler() {  
  5.             super(Looper.getMainLooper());  
  6.         }  
  7.   
  8.         public static InternalHandler getHandler(){  
  9.             if (sHandler == null) {  
  10.             handler = new InternalHandler();  
  11.             }  
  12.             return handler;  
  13.         }  
  14.          
  15.     }  
private static class InternalHandler extends Handler {
        private static InternalHandler handler;

        private InternalHandler() {
            super(Looper.getMainLooper());
        }

        public static InternalHandler getHandler(){
            if (sHandler == null) {
            handler = new InternalHandler();
            }
            return handler;
        }
       
    }
因为我们这是一个高并发的异步网络框架,当然需要加锁。否则,单例模式就失效了。那就用最有名的双重锁定吧。

  1. private static class InternalHandler extends Handler {  
  2.         private static InternalHandler handler;  
  3.   
  4.         private InternalHandler() {  
  5.             super(Looper.getMainLooper());  
  6.         }  
  7.   
  8.         public static InternalHandler getHandler(){  
  9.             if (handler==null){  
  10.                 synchronized (InternalHandler.class){  
  11.                     if (handler==null){  
  12.                     handler = new InternalHandler();  
  13.                     }  
  14.                 }  
  15.             }  
  16.             Log.d("InternalHandler",handler.toString());  
  17.             return handler;  
  18.         }  
  19.     }  
private static class InternalHandler extends Handler {
        private static InternalHandler handler;

        private InternalHandler() {
            super(Looper.getMainLooper());
        }

        public static InternalHandler getHandler(){
            if (handler==null){
                synchronized (InternalHandler.class){
                    if (handler==null){
                    handler = new InternalHandler();
                    }
                }
            }
            Log.d("InternalHandler",handler.toString());
            return handler;
        }
    }

然后,为了使用这个Handler那我只能把发送消息的handleMessage方法复写了。但是这个Message对象之前是个什么呢?是一个泛型T。这就让人比较困扰了。我们之前做的是将一个数据对象msg.obj提供给ThreadTask方法的onResult作为参数。执行result当中的方法。此处对应上面源码分析中为什么我发数据给主UI线程的时候需要把AsyncTask自己,及要发送的数据都发送过去这个写法上的疑问。

  1. public abstract class ThreadTask2<T> extends Thread{  
  2.     @Override  
  3.     public void run() {  
  4.         super.run();  
  5.         ...  
  6.     }  
  7.         ...  
  8.     /** 
  9.      * 子线程返回的结果,运行在主线程 
  10.      * */  
  11.     public abstract void onResult(T t);  
  12.         ...  
  13.     private static class InternalHandler  extends Handler {  
  14.         private static InternalHandler handler;  
  15.   
  16.   
  17.         private InternalHandler() {  
  18.             super(Looper.getMainLooper());  
  19.         }  
  20.   
  21.   
  22.         public static InternalHandler getHandler(){  
  23.             if (handler==null){  
  24.                 synchronized (InternalHandler.class){  
  25.                     if (handler==null){  
  26.                     handler = new InternalHandler();  
  27.                     }  
  28.                 }  
  29.             }  
  30.             Log.d("InternalHandler",handler.toString());  
  31.             return handler;  
  32.         }  
  33.   
  34.   
  35.         @Override  
  36.         public void handleMessage(Message msg) {  
  37.             super.handleMessage(msg);  
  38.             ---此处处理msg--  
  39.         }  
  40.     }  
  41.         ...  
  42. }  
public abstract class ThreadTask2<T> extends Thread{
    @Override
    public void run() {
        super.run();
        ...
    }
        ...
    /**
     * 子线程返回的结果,运行在主线程
     * */
    public abstract void onResult(T t);
        ...
    private static class InternalHandler extends Handler {
        private static InternalHandler handler;


        private InternalHandler() {
            super(Looper.getMainLooper());
        }


        public static InternalHandler getHandler(){
            if (handler==null){
                synchronized (InternalHandler.class){
                    if (handler==null){
                    handler = new InternalHandler();
                    }
                }
            }
            Log.d("InternalHandler",handler.toString());
            return handler;
        }


        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            ---此处处理msg--
        }
    }
        ...
}
现在在handleMessage中如何调用外部类ThreadTask的onResult方法呢?那么必须获取外部类的对象。参考一下AsyncTask对象中的方法:
  1. private static class AsyncTaskResult<Data> {  
  2.         final AsyncTask mTask;  
  3.         final Data[] mData;  
  4.   
  5.         AsyncTaskResult(AsyncTask task, Data... data) {  
  6.             mTask = task;  
  7.             mData = data;  
  8.         }  
  9.     }  
private static class AsyncTaskResult<Data> {
        final AsyncTask mTask;
        final Data[] mData;

        AsyncTaskResult(AsyncTask task, Data... data) {
            mTask = task;
            mData = data;
        }
    }
AsyncTask对象postResult方法:
  1. private Result postResult(Result result) {  
  2.         @SuppressWarnings("unchecked")  
  3.         Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,  
  4.                 new AsyncTaskResult<Result>(this, result));  
  5.         message.sendToTarget();  
  6.         return result;  
  7.     }  
private Result postResult(Result result) {
        @SuppressWarnings("unchecked")
        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
                new AsyncTaskResult<Result>(this, result));
        message.sendToTarget();
        return result;
    }
仿造后得到我们的代码:run方法中发送一个ResultData对象包含自身对象和一个耗时操作的返回值结果给handler,handler处理的时候先解析这个ResultData,再通过ThreadTask对象的onresult方法中处理数据。
  1. public abstract class ThreadTask2<T> extends Thread{  
  2.     @Override  
  3.     public void run() {  
  4.         super.run();  
  5.         Message message = Message.obtain();  
  6.         message.obj = new ResultData<>(this,onOoInBackground());  
  7.         handler.sendMessage(message);  
  8.     }  
  9.         ...  
  10.     private static class InternalHandler  extends Handler {  
  11.         private static InternalHandler handler;  
  12.   
  13.         private InternalHandler() {  
  14.             super(Looper.getMainLooper());  
  15.         }  
  16.   
  17.         public static InternalHandler getHandler(){  
  18.             if (handler==null){  
  19.                 synchronized (InternalHandler.class){  
  20.                     if (handler==null){  
  21.                     handler = new InternalHandler();  
  22.                     }  
  23.                 }  
  24.             }  
  25.             Log.d("InternalHandler",handler.toString());  
  26.             return handler;  
  27.         }  
  28.   
  29.         @Override  
  30.         public void handleMessage(Message msg) {  
  31.             super.handleMessage(msg);  
  32.             ResultData resultData = (ResultData) msg.obj;  
  33.             resultData.task2.onResult(resultData.data);  
  34.         }  
  35.     }  
  36.         ...  
  37.     private static class ResultData<T>{  
  38.         ThreadTask2 task2;  
  39.         T data;  
  40.   
  41.         public ResultData(ThreadTask2 task2, T data) {  
  42.             this.task2 = task2;  
  43.             this.data = data;  
  44.         }  
  45.     }  
  46. }  
public abstract class ThreadTask2<T> extends Thread{
    @Override
    public void run() {
        super.run();
        Message message = Message.obtain();
        message.obj = new ResultData<>(this,onOoInBackground());
        handler.sendMessage(message);
    }
        ...
    private static class InternalHandler extends Handler {
        private static InternalHandler handler;

        private InternalHandler() {
            super(Looper.getMainLooper());
        }

        public static InternalHandler getHandler(){
            if (handler==null){
                synchronized (InternalHandler.class){
                    if (handler==null){
                    handler = new InternalHandler();
                    }
                }
            }
            Log.d("InternalHandler",handler.toString());
            return handler;
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            ResultData resultData = (ResultData) msg.obj;
            resultData.task2.onResult(resultData.data);
        }
    }
        ...
    private static class ResultData<T>{
        ThreadTask2 task2;
        T data;

        public ResultData(ThreadTask2 task2, T data) {
            this.task2 = task2;
            this.data = data;
        }
    }
}
打印日志看看是否成功。
Log日志如下:发现一直都是同一个Handler对象。成功。

  1. 12-22 19:08:41.438  8805-8805/com.simple.simpledemo D/InternalHandler: Handler (com.simple.simpledemo.ThreadTask2$InternalHandler) {424498a8}  
  2. 12-22 19:08:41.448  8805-8805/com.simple.simpledemo D/ThreadTask: 我是加载动画  
  3. 12-22 19:08:44.448  8805-9061/com.simple.simpledemo D/ThreadTask: 我是执行过程  
  4. 12-22 19:08:44.448  8805-8805/com.simple.simpledemo D/ThreadTask: 结果结果返回  
  5. 12-22 19:08:47.238  8805-8805/com.simple.simpledemo D/InternalHandler: Handler (com.simple.simpledemo.ThreadTask2$InternalHandler) {424498a8}  
  6. 12-22 19:08:47.248  8805-8805/com.simple.simpledemo D/ThreadTask: 我是加载动画  
  7. 12-22 19:08:50.248  8805-9155/com.simple.simpledemo D/ThreadTask: 我是执行过程  
  8. 12-22 19:08:50.248  8805-8805/com.simple.simpledemo D/ThreadTask: 结果结果返回  
12-22 19:08:41.438 8805-8805/com.simple.simpledemo D/InternalHandler: Handler (com.simple.simpledemo.ThreadTask2$InternalHandler) {424498a8}
12-22 19:08:41.448 8805-8805/com.simple.simpledemo D/ThreadTask: 我是加载动画
12-22 19:08:44.448 8805-9061/com.simple.simpledemo D/ThreadTask: 我是执行过程
12-22 19:08:44.448 8805-8805/com.simple.simpledemo D/ThreadTask: 结果结果返回
12-22 19:08:47.238 8805-8805/com.simple.simpledemo D/InternalHandler: Handler (com.simple.simpledemo.ThreadTask2$InternalHandler) {424498a8}
12-22 19:08:47.248 8805-8805/com.simple.simpledemo D/ThreadTask: 我是加载动画
12-22 19:08:50.248 8805-9155/com.simple.simpledemo D/ThreadTask: 我是执行过程
12-22 19:08:50.248 8805-8805/com.simple.simpledemo D/ThreadTask: 结果结果返回

现在这一版本的ThreadTask已经非常接近AsyncTask类的实现了。就差一个线程池的距离。

(三)线程池实现的进阶版举例

为什么要使用线程池,因为之前的该方案不断的创建线程。既然不断创建新线程那么就有新建和销毁的大量开销。关于线程池

那就简单写个线程池吧:写一个定长线程池:

  1. //定义一个定长线程池  
  2.     private static ExecutorService executorService = Executors.newFixedThreadPool( 3);  
//定义一个定长线程池
    private static ExecutorService executorService = Executors.newFixedThreadPool(3);
再把复写的run方法修改一下:

  1. public void run() {  
  2.         executorService.execute(new Runnable() {  
  3.             @Override  
  4.             public void run() {  
  5.                 Message message = Message.obtain();  
  6.                 message.obj = new ResultData<>(ThreadTask3.this,onOoInBackground());  
  7.                 handler.sendMessage(message);  
  8.             }  
  9.         });  
  10.     }  
public void run() {
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                Message message = Message.obtain();
                message.obj = new ResultData<>(ThreadTask3.this,onOoInBackground());
                handler.sendMessage(message);
            }
        });
    }
然后让代码不再继承自Thread方法,将execute方法改了:

  1. public void execute(){  
  2.         onStart();  
  3.         run();  
  4.     }  
public void execute(){
        onStart();
        run();
    }
运行代码,查看结果:貌似肉眼看不出区别。写个循环验证一下:
  1. for (int i = 0; i < 30; i++) {  
  2.             final int index = i;  
  3.             new ThreadTask3<String>() {  
  4.                 @Override  
  5.                 public void onStart() {  
  6.                     Log.d("ThreadTask""我是加载动画");  
  7.                 }  
  8.   
  9.                 @Override  
  10.                 public String onOoInBackground() {  
  11.                     Log.e("ThreadTask""测试日志" + index);  
  12.                     try {  
  13.                         Thread.sleep(3000);  
  14.                     } catch (InterruptedException e) {  
  15.                         e.printStackTrace();  
  16.                     }  
  17.                     Log.d("ThreadTask""我是执行过程");  
  18.                     return "结果返回";  
  19.                 }  
  20.   
  21.                 @Override  
  22.                 public void onResult(String s) {  
  23.                     Log.d("ThreadTask""结果" + s);  
  24.                     my_text.setText("结果" + s);  
  25.                 }  
  26.             }.execute();  
  27.         }  
for (int i = 0; i < 30; i++) {
            final int index = i;
            new ThreadTask3<String>() {
                @Override
                public void onStart() {
                    Log.d("ThreadTask", "我是加载动画");
                }

                @Override
                public String onOoInBackground() {
                    Log.e("ThreadTask", "测试日志" + index);
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Log.d("ThreadTask", "我是执行过程");
                    return "结果返回";
                }

                @Override
                public void onResult(String s) {
                    Log.d("ThreadTask", "结果" + s);
                    my_text.setText("结果" + s);
                }
            }.execute();
        }
外面加了一个循环执行线程的任务,里面通过Log.e("ThreadTask", "测试日志" + index)打印日志。发现如下效果:

因为我将线程池大小设置为3,每次打印3条数据,一直到结束。因为我们执行过程有3秒。每次打印之后都有3秒等待。

效果我们已经知道了,再回想一下AsyncTask的代码,发现它用的就是线程池,不过是一个自定义线程池罢了。当然还是有少量优化上的差异。但,通过这个Demo是否更加了解了AsyncTask源码的意义及优缺点?

到此就讲完了。感谢阅读。over。