android中进程间通信之IPC机制

时间:2022-09-21 16:13:13

Android中涉及到的异步机制有Handler和AsyncTask,但AsyncTask内部也是使用Handler来传递消息,而且基于线程池。因此明显的AsyncTask比Handler要重量级

AsyncTask的基本实现原理:

  • AsyncTask内部维护了一个线程池,以及InternalHandler继承了Handler,我们的调用方法execute()的时候,AsyncTask会判断内部运行状态,只有是待定(pending)状态下才能继续执行,而且在其内部使用自己默认的Executor(内部继承Executor的SerialExecutor类)来执行execute()方法,并且在这之前调用onPreExecute()方法(运行在主线程),用于让我们在线程开始之前做一些准备工作

  • AsyncTask的初始状态为PENDING,代表待定状态,RUNNING代表执行状态,FINISHED代表结束状态
    线程开始之后会调用设置当前线程的优先级为后台线程:
    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

  • 接着调用doInBackground()方法,
    在FutureTask(可以中途取消的用于异步计算的类)实例中,将会调用WorkerRunnable做后台任务,完成之后会调用done方法,在done()方法中无论任务取消还是执行成功都会发送消息,由Handler执行
    在线程管理器池ThreadPoolExecutor的execute函数中,我们看到这段代码的主要功能是将异步任务mFuture加入到将要执行的队列中

  • 概括来说,当我们调用execute(Params… params)方法后,execute方法会调用onPreExecute()方法,然后在SerialExecutor(串行执行器)的execute(子线程)方法中来调用ThreadPoolExecutor实例执行一个FutureTask任务,这个过程中doInBackground(Params… params)将被调用,如果被开发者覆写的doInBackground(Params… params)方法中调用了publishProgress(Progress… values)方法,则通过InternalHandler实例sHandler发送一条MESSAGE_POST_PROGRESS消息,更新进度,sHandler处理消息时onProgressUpdate(Progress… values)方法将被调用;如果遇到异常,则发送一条MESSAGE_POST_CANCEL的消息,取消任务,sHandler处理消息时onCancelled()方法将被调用;如果执行成功,则发送一条MESSAGE_POST_RESULT的消息,显示结果,sHandler处理消onPostExecute(Result
    result)方法被调用。

为了正确的使用AsyncTask类,以下是几条必须遵守的准则:
<1>Task的实例必须在UI thread中创建
<2>execute方法必须在UI thread中调用
<3>不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params…), onProgressUpdate(Progress…)这几个方法
<4> 该task只能被执行一次,否则多次调用时将会出现异常
详见:http://blog.csdn.net/bboyfeiyu/article/details/8973058

关于AsyncTask你所不知道的事:
其实在我们在主线程中实例化AsyncTask之后,调用其execute()方法,AsyncTask会使用期内部的serialExecutor来执行后台任务,SerialExecutor在AsyncTask中是以常量的形式被使用的,因此在整个应用程序中的所有AsyncTask实例都会共用同一个SerialExecutor,SerialExecutor是使用ArrayDeque这个队列来管理Runnable对象的,每次我们添加任务都是直接添加到队列尾部,每次当一个任务执行完毕后,下一个任务才会得到执行,SerialExecutor模仿的是单一线程池的效果,如果我们快速地启动了很多任务,同一时刻只会有一个线程正在执行,其余的均处于等待状态

AsyncTask什么时候从后台子线程切换到UI线程的?
我们知道AsyncTask里面封装了handler用于处理消息,正式在handleMessage()方法里面调用onProgressUpdate()方法,我们才能在UI线程里面更新进度,而只有在doInBackground()方法中调用publishProgress()方法才可以在PublishProgress()方法中发送消息给handler,从而完成对UI元素的更新操作。其实也没有什么神秘的,因为说到底,AsyncTask也是使用的异步消息处理机制,只是做了非常好的封装而已
详见:http://blog.csdn.net/guolin_blog/article/details/11711405