Android系统线程间通信方式之AsyncTask机制

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/litao55555/article/details/82972330

比较好的博客:
https://blog.csdn.net/qq_30379689/article/details/53203556
https://blog.csdn.net/guolin_blog/article/details/11711405
AsyncTask是对Handler与线程池的封装,目的也是实现线程间的通信,子线程执行耗时操作发送消息到主线程更新UI,使用线程池的主要原因是避免不必要的创建及销毁线程的开销

1. AsyncTask的使用方法

public class MainActivity extends Activity implements Button.OnClickListener {
		@Override
		protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		Button bt_down = (Button) findViewById(R.id.button)
    		bt_down.setOnClickListener(new View.OnClickListener() {
				    @Override
				    public void onClick(View v) {
				        try {
				            URL url = new URL("http://blog.csdn.net/");
				            new MyAsyncTask().execute(url);					//0. 执行execute开始执行异步任务
				        } catch (MalformedURLException e) {
				            e.printStackTrace();
				        }
				    }
				});
    }
		
    private class MyAsyncTask extends AsyncTask<URL, Integer, Long> {		//AsyncTask是一个抽象类,Handler是一个普通的类
		    @Override
		    protected void onPreExecute() {													//1. 主线程执行onPreExecute(执行异步任务前执行)
		        //异步任务开启之前回调,在主线程中执行
		        super.onPreExecute();
		    }
		    @Override
		    protected Long doInBackground(URL... urls) {						//2. 线程池执行doInBackground(执行异步任务)
		        //执行异步任务,在线程池中执行
		        long totalSize = 0;
		        int i = 0;
		        try {
		            while (i < 100) {
		                Thread.sleep(50);
		                i = i + 5;
		                publishProgress(i);
		            }
		        } catch (InterruptedException e) {
		            e.printStackTrace();
		        }
		        totalSize = totalSize + i;
		        return totalSize;
		    }
		    @Override
		    protected void onProgressUpdate(Integer... progress) {	//3. 执行doInBackground的过程中执行publishProgress,主线程回调执行onProgressUpdate
		        //当doInBackground中调用publishProgress时回调,在主线程中执行
		        pb_progress.setProgress(progress[0]);
		    }
		    @Override
		    protected void onPostExecute(Long result) {							//4. 主线程执行onPostExecute(执行异步任务后执行)
		        //在异步任务执行之后回调,在主线程中执行
		        Toast.makeText(MainActivity.this, "下载完成,结果是" + result, Toast.LENGTH_SHORT).show();
		    }
		    @Override
		    protected void onCancelled() {													//5. 异步任务被取消时回调
		        //在异步任务被取消时回调
		        super.onCancelled();
		    }
	  }
}

AsyncTask的三个泛型参数:
a. Params:异步任务的参数,在执行AsyncTask时需要传入的参数,可用于在后台任务中使用。
b. Progress:进度条相关,后台任务执行时,如果需要在界面上显示当前的进度,则使用这里指定的泛型作为进度单位。
c. Result:任务的执行结果,当任务执行完毕后,如果需要对结果进行返回,则使用这里指定的泛型作为返回值类型。

参考:https://blog.csdn.net/guolin_blog/article/details/11711405
a. onPreExecute():在后台任务执行之前调用 //用于界面的初始化操作,比如显示一个进度条对话框等。
b. doInBackground(Params…):在子线程中运行 //处理耗时任务,任务一旦执行完毕就可以通过return语句来将任务的执行结果result进行返回
如果AsyncTask的第三个泛型参数指定的是void,就可以不返回任务执行结果。注意,在这个方法中是不可以进行UI操作的,如果需要更新UI元素,比如说反馈当前任务的执行进度,
可以调用publishProgress(Progress…)方法来完成。
c. onProgressUpdate(Progress…):当在doInBackground中调用了publishProgress(Progress…)方法后,这个方法就很快会被调用,方法中携带的参数就是在后台任务中传递过来的。
在这个方法中可以对UI进行操作,利用参数中的数值就可以对界面元素进行相应的更新。
d. onPostExecute(Result):在后台任务执行之后调用,当后台任务执行完毕并通过return语句将执行结果result返回时,这个方法就很快会被调用。返回的数据result会作为参数传递到此方法中,
可以利用返回的数据来进行一些UI操作,比如说提醒任务执行的结果,以及关闭掉进度条对话框等。

AsyncTask用法总结:
首先定义一个继承自AsyncTask的MyAsyncTask并复写onPreExecute、doInBackground、onPostExecute方法
主线程实例化MyAsyncTask,并调用execute方法,会依次执行onPreExecute、doInBackground、onPostExecute方法
其中onPreExecute和onPostExecute在主线程中执行,doInBackground在子线程中执行,doInBackground在执行publishProgress时会回调到主线程执行onProgressUpdate刷新UI

2. 源码分析:new MyAsyncTask().execute(url);

2.1 分析new MyAsyncTask()

public abstract class AsyncTask<Params, Progress, Result> {		//Params = URL, Progress = Integer, Result = Long
	public AsyncTask() {					//执行new MyAsyncTask()
	    this((Looper) null);				---------------------------
	}                                                                 |
	public AsyncTask(@Nullable Looper callbackLooper) {		<----------
        mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
            ? getMainHandler()				//并不是获得主线程的Handler,而是获得内部类AsyncTask.InternalHandler
            : new Handler(callbackLooper);
        mWorker = new WorkerRunnable<Params, Result>() {
            public Result call() throws Exception {				//复写call()方法,执行call()时会执行doInBackground
                mTaskInvoked.set(true);
                Result result = null;
                try {
                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                    result = doInBackground(mParams);
                    Binder.flushPendingCommands();
                } catch (Throwable tr) {
                    ...
                } finally {
                    postResult(result);
                }
                return result;
            }
        };
        mFuture = new FutureTask<Result>(mWorker) {		--------------------------
            @Override                                                            |
            protected void done() {                                              |
                try {                                                            |
                    postResultIfNotInvoked(get());                               |
                }                                                                |
            }                                                                    |
        };                                                                       |
    }                                                                            |
}                                                                                |
public class FutureTask<V> implements RunnableFuture<V> {		<-----------------
		public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;										//FutureTask.callable = mWorker
        this.state = NEW;
    }
}

总结:
执行new MyAsyncTask()实例化一个AsyncTask,且AsyncTask.mFuture = new FutureTask(mWorker),且mWorker = new WorkerRunnable<Params, Result>()
在new WorkerRunnable()时会复写call()方法,执行call()时会执行doInBackground

2.2 分析MyAsyncTask.execute(url);

frameworks\base\core\java\android\os\AsyncTask.java:
public abstract class AsyncTask<Params, Progress, Result> {
	public final AsyncTask<Params, Progress, Result> execute(Params... params) {
	    return executeOnExecutor(sDefaultExecutor, params);
	}
	public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,		//exec = sDefaultExecutor = SERIAL_EXECUTOR = new SerialExecutor()
	        Params... params) {																													//params = new URL("http://blog.csdn.net/")
	    if (mStatus != Status.PENDING) {		//只有异步任务的状态是PENDING时才可以往下执行
	        switch (mStatus) {
	            case RUNNING:
	                throw new IllegalStateException("...");
	            case FINISHED:
	                throw new IllegalStateException("...");
	        }
	    }
	    mStatus = Status.RUNNING;						//异步任务的状态变为RUNNING,此时如果再一次使用execute执行异步任务时会抛出异常IllegalStateException
	    onPreExecute();											//重点:1. 主线程执行onPreExecute
	    mWorker.mParams = params;
	    exec.execute(mFuture);	------------------------------------------------------	//exec = new SerialExecutor(),mFuture = new FutureTask(mWorker),mWorker = new WorkerRunnable()
	    return this;                                                                 |		且mWorker.mParams = new URL("http://blog.csdn.net/")
	}                                                                                |
                                                                                     |
			||主线程创建子线程,并切换到子线程中执行run()                               |
		\/                                                                           |
  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();		--------------------------------------------	//r = mFuture = new FutureTask(mWorker),其中FutureTask.callable = mWorker
                } finally {                                                    |
                    scheduleNext();                                            |
                }                                                              |
            }                                                                  |
        });                                                                    |
        if (mActive == null) {                                                 |
            scheduleNext();                                                    |
        }                                                                      |
    }                                                                          |
    protected synchronized void scheduleNext() {                               |
        if ((mActive = mTasks.poll()) != null) {                               |
            THREAD_POOL_EXECUTOR.execute(mActive);                             |
        }                                                                      |
    }                                                                          |
	}                                                                          |
}                                                                              |
                                                                               |
public class FutureTask<V> implements RunnableFuture<V> {                      |
		public void run() {		<-----------------------------------------------
        if (state != NEW ||
            !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
            return;
        try {
            Callable<V> c = callable;					//c = FutureTask.callable = mWorker,其中mWorker = new WorkerRunnable()
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call();		-------------------------------------------------	//执行mWorker.call(),会回调doInBackground
                    ran = true;                                                             |
                } catch (Throwable ex) {                                                    |
                    result = null;                                                          |
                    ran = false;                                                            |
                    setException(ex);                                                       |
                }                                                                           |
                if (ran)                                                                    |
                    set(result);                                                            |
            }                                                                               |
        } finally {                                                                         |
            ...																			    |
        }                                                                                   |
    }                                                                                       |
}                                                                                           |
                                                                                            |
public abstract class AsyncTask<Params, Progress, Result> {                                 |
		public AsyncTask(@Nullable Looper callbackLooper) {                                 |
        mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()       |
            ? getMainHandler()                                                              |
            : new Handler(callbackLooper);                                                  |
        mWorker = new WorkerRunnable<Params, Result>() {                                    |
            public Result call() throws Exception {		<------------------------------------
                mTaskInvoked.set(true);
                Result result = null;
                try {
                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                    result = doInBackground(mParams);																	//重点:2. 子线程执行doInBackground
                    Binder.flushPendingCommands();
                } catch (Throwable tr) {
                    ...
                } finally {
                    postResult(result);		-------------------------
                }                                                   |
                return result;                                      |
            }                                                       |
        };                                                          |
    }                                                               |
    private Result postResult(Result result) {		<----------------
        @SuppressWarnings("unchecked")
        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,			---------
                new AsyncTaskResult<Result>(this, result));                                 |
        message.sendToTarget();     -------------------------------------------------------------------------
        return result;                                                                      |               |
    }                                                                                       |               |
    private Handler getHandler() {		<---------------------------------------------------|               |
        return mHandler;		//mHandler = AsyncTask.InternalHandler		            	|               |
    }                                                                                       |               |
}                                                                                           |               |
                                                                                            |               |
分析mHandler																				|				|
public abstract class AsyncTask<Params, Progress, Result> {                                 |               |
	public AsyncTask(@Nullable Looper callbackLooper) {                                     |               |
        mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()       |               |
            ? getMainHandler()			-------------------                                 |               |
            : new Handler(callbackLooper);                |                                 |               |
	}                                                     |                                 |               |
	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);                                                                  |               |
        }                                                                                   |               |
        @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;                                                                  |               |
            }                                                                               |               |
        }                                                                                   |               |
    }                                                                                       |               |
}                                                                                           |               |
                                                                                            |               |
                                                                                            |               |
                                                                                            |               |
public class Handler {                                                                      |               |
		public final Message obtainMessage(int what, Object obj){    <-----------------------               |
        return Message.obtain(this, what, obj);			----------------------                              |
    }                                                                        |                              |
}                                                                            |                              |
                                                                             |                              |
public final class Message implements Parcelable {                           |                              |
		public static Message obtain(Handler h, int what, Object obj) {	<-----                              |
        Message m = obtain();                                                                               |
        m.target = h;								//Message.target = mHandler = AsyncTask.InternalHandler
        m.callback = callback;			//Message.callback = MESSAGE_POST_RESULT                            |
        m.obj = obj;								//Message.obj = new AsyncTaskResult<Result>(this, result)),其中result = doInBackground(mParams);
        return m;                                                                                           |
    }                                                                                                       |
		public void sendToTarget() {	<--------------------------------------------------------------------
        target.sendMessage(this);		--------------------------------------------------
    }                                                                                    |
}                                                                                        |
                                                                                         |
                                                                                   		 |
		||使用Handler机制,子线程发送一个Message切换到主线程                                |
		\/                                                                             	 |
																																			 |
public abstract class AsyncTask<Params, Progress, Result> {                              |
		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; 				//result = new AsyncTaskResult<Result>(this, result)),其中this = new MyAsyncTask(),result = doInBackground(mParams);
            switch (msg.what) {                                                                                               |
                case MESSAGE_POST_RESULT:                                                                                     |
                    // There is only one result                                                                               |
                    result.mTask.finish(result.mData[0]);		----------------------	//result.mTask = new MyAsyncTask()    |
                    break;                                                           |    result.mData[0] = result = doInBackground(mParams);
                case MESSAGE_POST_PROGRESS:                                          |                                        |
                    result.mTask.onProgressUpdate(result.mData);                     |                                        |
                    break;                                                           |                                        |
            }                                                                        |                                        |
        }                                                                            |                                        |
    }                                                                                |                                        |
    private void finish(Result result) {	<-----------------------------------------                                        |
        if (isCancelled()) {   //如果当前任务已经被取消掉了,就会调用onCancelled()方法	                                          |
            onCancelled(result);                                                                                              |
        } else {                                                                                                              |
            onPostExecute(result); 		//重点:3. 主线程执行onPostExecute,result为执行doInBackground的返回值                   |
        }                                                                                                                     |
        mStatus = Status.FINISHED;	//任务执行完毕,状态设置为FINISHED                                                          |
    }                                                                                                                         |
}                                                                                                                             |
                                                                                                                              |
public abstract class AsyncTask<Params, Progress, Result> {                                                                   |
    private static class AsyncTaskResult<Data> {			<------------------------------------------------------------------
        final AsyncTask mTask;
        final Data[] mData;
        AsyncTaskResult(AsyncTask task, Data... data) {
            mTask = task;						//AsyncTaskResult.mTask = MyAsyncTask
            mData = data;						//AsyncTaskResult.mData = result = doInBackground(mParams);
        }
    }
}


若在doInBackground中调用了publishProgress(Progress...)方法,会调用onProgressUpdate(Progress...),过程分析如下:
public abstract class AsyncTask<Params, Progress, Result> {
		protected final void publishProgress(Progress... values) {
        if (!isCancelled()) {
            getHandler().obtainMessage(MESSAGE_POST_PROGRESS,		  ------------------
                    new AsyncTaskResult<Progress>(this, values)).sendToTarget();  -----|-------------------------
        }                                                                              |                        |
    }                                                                                  |                        |
}                                                                                      |                        |
public class Handler {                                                                 |                        |
		public final Message obtainMessage(int what, Object obj){		<---------------                        |
        return Message.obtain(this, what, obj);		-------------------------                                   |
    }                                                                       |                                   |
}                                                                           |                                   |
public final class Message implements Parcelable {                          |                                   |
    public static Message obtain(Handler h, int what, Object obj) {		<----                                   |
        Message m = obtain();                                                                                   |
        m.target = h;			//Message.target = mHandler = AsyncTask.InternalHandler                         |
        m.what = what;		//Message.what = MESSAGE_POST_PROGRESS                                              |
        m.obj = obj;      //Message.obj = new AsyncTaskResult<Progress>(this, values)).sendToTarget();          |
        return m;                                                                                               |
    }                                                                                                           |
    public void sendToTarget() {		<------------------------------------------------------------------------
        target.sendMessage(this);
    }
}

					||使用Handler机制,子线程发送一个Message切换到主线程
					\/
					
public abstract class AsyncTask<Params, Progress, Result> {
		private static class InternalHandler extends Handler {
        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);		//重点:4. 主线程执行onProgressUpdate,result.mTask = new MyAsyncTask()
                    break;
            }
        }
    }
}

在定义MyAsyncTask时复写onCancelled(),在哪里被调用?

public abstract class AsyncTask<Params, Progress, Result> {
		private void finish(Result result) {
        if (isCancelled()) {   //如果当前任务已经被取消掉了,就会调用onCancelled()方法
            onCancelled(result);		//重点:5. 主线程执行onCancelled,result为执行doInBackground的返回值
        } else {
            onPostExecute(result);
        }
        mStatus = Status.FINISHED;
    }
}

3. 几个问题

3.1 如果多次执行MyAsyncTask.execute()会重复执行异步任务吗?

不会,当第一次执行MyAsyncTask.execute()时MyAsyncTask.mStatus = Status.PENDING,不会抛出异常,且将状态改变为MyAsyncTask.mStatus = Status.RUNNING
当第二次执行MyAsyncTask.execute()时MyAsyncTask.mStatus != Status.PENDING,会抛出异常,不会往下执行,所以不会多次执行异步任务

3.2 MyAsyncTask.execute()时依次执行onPreExecute、doInBackground、onPostExecute方法,且onPreExecute和onPostExecute在主线程中执行,doInBackground在子线程中执行那么从onPreExecute到doInBackground是如何从主线程切换到子线程?从doInBackground到onPostExecute是如何从子线程切换到主线程?

执行MyAsyncTask.execute()时会在主线程执行onPreExecute,接着会使用SerialExecutor创建子线程,并在子线程中执行doInBackground,最终会执行postResult
使用Handler机制发送一个Message切换到主线程执行onProgressUpdate刷新UI

AsyncTask原理总结:

执行MyAsyncTask.execute()时会在主线程执行onPreExecute,接着会使用SerialExecutor创建子线程,并在子线程中执行doInBackground,最终会执行postResult将doInBackground的
执行结果result保存到AsyncTaskResult.mData中,将AsyncTaskResult保存到Message.obj中,使用Handler机制发送一个Message切换到主线程,取出result,判断当前异步任务是否已经被取消,
如果已经被取消则会调用onCancelled()方法,如果没有被取消则会调用onPostExecute
当在执行doInBackground的过程中如果执行publishProgress时会使用Handler机制发送一个Message切换到主线程执行onProgressUpdate刷新UI

猜你喜欢

转载自blog.csdn.net/litao55555/article/details/82972330