Android - 消息机制与线程通信
以下资料摘录整理自老罗的Android之旅博客,是对老罗的博客关于Android底层原理的一个抽象的知识概括总结(如有错误欢迎指出)(侵删):
http://blog.csdn.net/luoshengyang/article/details/8923485
http://blog.csdn.net/luoshengyang/article/details/12957169
整理by Doing
消息机制
- 带有消息队列,用来执行循环性任务:有消息时就处理;没有消息时就睡眠;(例子:主线程、android.os.HandlerThread)
- 没有消息队列,用来执行一次性任务:任务一旦执行完成便退出;(例子:java.lang.Thread)


消息循环
- 创建Java层的Looper: 在Java层,创建了一个Looper对象,这个Looper对象是用来进入消息循环的,它的内部有一个消息队列MessageQueue对象mQueue:

- Looper类的静态成员函数prepareMainLooper是专门应用程序的主线程调用的,应用程序的其它子线程都不应该调用这个函数来在本线程中创建消息循环对象,而应该调用prepare函数来在本线程中创建消息循环对象:其它地方能够方便地通过Looper类的getMainLooper函数来获得应用程序主线程中的消息循环对象,进而能够向应用程序主线程发送消息。

- 创建JNI层的Looper对象:在JNI层,创建了一个NativeMessageQueue对象,这个NativeMessageQueue对象保存在Java层的消息队列对象mQueue的成员变量mPtr中; 在C++层,创建了一个Looper对象,保存在JNI层的NativeMessageQueue对象的成员变量mLooper中,这个对象的作用是,当Java层的消息队列中没有消息时,就使Android应用程序主线程进入等待状态,而当Java层的消息队列中来了新的消息后,就唤醒Android应用程序的主线程来处理这个消息:
- 一种进程/线程间通信机制
- 包含一个写端文件描述符和一个读端文件描述符
- Looper通过读端文件描述符等待新消息的到来
- Handler通过写端文件描述符通知Looper新消息的到来

- 一种I/O多路复用技术,select/poll加强版
- epoll_create:创建一个epoll句柄
- epoll_ctl:设置要监控的文件描述符
- epoll_wait:等待监控的文件描述符发生IO事件
消息的发送
- 在ActivityThread.queueOrSendMessage函数中,把上面传进来的参数封装成一个Message对象msg,然后通过mH.sendMessage函数把这个消息对象msg加入到应用程序的消息队列中去。(mH为H类,继承于Handler类)
- 在Looper::wake()中,通过打开文件描述符mWakeWritePipeFd往管道的写入一个"W"字符串。其实,往管道写入什么内容并不重要,往管道写入内容的目的是为了唤醒应用程序的主线程。
- Handler.sendMessage:带一个Message参数,用来描述消息的内容
- Handler.post:带一个Runnable参数,会被转换为一个Message参数

消息的处理
总结
消息在异步任务的应用
- 执行组件生命周期函数
- 执行业务逻辑
- 执行用户交互
- 执行UI渲染
- Service生命周期函数 – 20s
- Broadcast Receiver接收前台优先级广播函数 –10s
- Broadcast Receiver接收后台优先级广播函数 – 60s
- 影响输入事件处理的函数 – 5s
- 影响进程启动的函数 – 10s
- 影响Activity切换的函数– 2s
- android.os.HandlerThread:适合用来处于不需要更新UI的后台任务
- android.os.AyncTask:适合用来处于需要更新UI的后台任务
HandlerThread
- HandlerThread类继承了Thread类,因此,通过它可以在应用程序中创建一个子线程;其次,在它的run函数中,首先是调用Looper类的静态成员函数prepare来准备一个消息循环对象,然后会进入一个消息循环中,因此,这个子线程可以常驻在应用程序中,直到它接收收到一个退出消息为止。
- Looper类的myLooper成员函数将这个子线程中的消息循环对象保存在HandlerThread类中的成员变量mLooper中, 这样,其它地方就可以方便地通过它的getLooper函数来获得这个消息循环对象了,有了这个消息循环对象后,就可以往这个子线程的消息队列中发送消息,通知这个子线程执行特定的任务了

AsyncTask类
- 内部实现ThreadPoolExecutor类线程池
- 获取创建AsyncTask对象的当前所在线程的Handler进行消息发送和处理
- 当第一次创建一个AsyncTask对象时,首先会创建一个线程池sExecutor(ThreadPoolExecutor类,是Java提供的多线程机制之一。)
- ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
- BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory)
- 创建好了线程池后,再创建一个消息处理器:
- 创建AsyncTask对象,即执行AsyncTask类的构造函数:
- public AsyncTask() {
- mWorker = new WorkerRunnable<Params, Result>() {
- public Result call() throws Exception {
- ......
- return doInBackground(mParams);
- }
- };
- mFuture = new FutureTask<Result>(mWorker) {
- @Override
- protected void done() {
- Message message;
- Result result = null;
- try {
- result = get();
- } catch (InterruptedException e) {
- android.util.Log.w(LOG_TAG, e);
- } catch (ExecutionException e) {
- throw new RuntimeException("An error occured while executing doInBackground()",
- e.getCause());
- } catch (CancellationException e) {
- message = sHandler.obtainMessage(MESSAGE_POST_CANCEL,
- new AsyncTaskResult<Result>(AsyncTask.this, (Result[]) null));
- message.sendToTarget();
- return;
- } catch (Throwable t) {
- throw new RuntimeException("An error occured while executing "
- + "doInBackground()", t);
- }
- message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
- new AsyncTaskResult<Result>(AsyncTask.this, result));
- message.sendToTarget();
- }
- };
- }
- private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
- Params[] mParams;
- }
- public final AsyncTask<Params, Progress, Result> execute(Params... params) {
- ......
- mWorker.mParams = params;
- sExecutor.execute(mFuture);
- return this;
- }
- mWorker = new WorkerRunnable<Params, Result>() {
- public Result call() throws Exception {
- ......
- return doInBackground(mParams);
- }
- };
- private static class AsyncTaskResult<Data> {
- final AsyncTask mTask;
- final Data[] mData;
- AsyncTaskResult(AsyncTask task, Data... data) {
- mTask = task;
- mData = data;
- }
- }
- message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
- new AsyncTaskResult<Result>(AsyncTask.this, result));
- message.sendToTarget();
- private static class InternalHandler extends Handler {
- @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;
- ......
- }
- }
- }
- private void finish(Result result) {
- ......
- onPostExecute(result);
- ......
- }
- 在任务执行的过程当中,即执行doInBackground函数时候,可能通过调用publishProgress函数来将中间结果封装成一个消息发送到应用程序主线程中的消息队列中去,这个消息最终也是由InternalHandler类的handleMessage函数来处理的(这个函数是在应用程序的主线程中执行的,因此,它和前面的onPostExecute函数一样,可以操作应用程序的界面):
- protected final void publishProgress(Progress... values) {
- sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
- new AsyncTaskResult<Progress>(this, values)).sendToTarget();
- }
键盘(Keyboard)消息处理机制
InputManager的初始化工作
应用程序注册键盘消息接收通道的过程
InputManager分发键盘消息给应用程序的过程
应用程序注销键盘消息接收通道的过程
Android - 消息机制与线程通信的更多相关文章
- Android消息机制
每一个Android应用在启动的时候都会创建一个线程,这个线程被称为主线程或者UI线程,Android应用的所有操作默认都会运行在这个线程中. 但是当我们想要进行数据请求,图片下载,或者其他耗时操作时 ...
- Android消息机制:Looper,MessageQueue,Message与handler
Android消息机制好多人都讲过,但是自己去翻源码的时候才能明白. 今天试着讲一下,因为目标是讲清楚整体逻辑,所以不追究细节. Message是消息机制的核心,所以从Message讲起. 1.Mes ...
- Android开发之漫漫长途 ⅥI——Android消息机制(Looper Handler MessageQueue Message)
该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...
- Android开发之漫漫长途 Ⅶ——Android消息机制(Looper Handler MessageQueue Message)
该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...
- android 进程间通信 messenger 是什么 binder 跟 aidl 区别 intent 进程间 通讯? android 消息机制 进程间 android 进程间 可以用 handler么 messenger 与 handler 机制 messenger 机制 是不是 就是 handler 机制 或 , 是不是就是 消息机制 android messenge
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha messenger 是什么 binder 跟 aidl 区别 intent 进程间 通讯 ...
- Android 进阶14:源码解读 Android 消息机制( Message MessageQueue Handler Looper)
不要心急,一点一点的进步才是最靠谱的. 读完本文你将了解: 前言 Message 如何获取一个消息 Messageobtain 消息的回收利用 MessageQueue MessageQueue 的属 ...
- Android消息机制探索(Handler,Looper,Message,MessageQueue)
概览 Android消息机制是Android操作系统中比较重要的一块.具体使用方法在这里不再阐述,可以参考Android的官方开发文档. 消息机制的主要用途有两方面: 1.线程之间的通信.比如在子线程 ...
- Android进阶——Android消息机制之Looper、Handler、MessageQueen
Android消息机制可以说是我们Android工程师面试题中的必考题,弄懂它的原理是我们避不开的任务,所以长痛不如短痛,花点时间干掉他,废话不多说,开车啦 在安卓开发中,常常会遇到获取数据后更新UI ...
- Android消息机制不完全解析(上)
Handler和Message是Android开发者常用的两个API,我一直对于它的内部实现比较好奇,所以用空闲的时间,阅读了一下他们的源码. 相关的Java Class: androi ...
随机推荐
- addEventListener之handleEvent
addEventListener() 方法是将指定的事件监听器注册到目标对象上,当该对象触发指定的事件时,指定的回调函数就会被执行.语法: element.addEventListener(type, ...
- vim 支持gb2312
vi /etc/vimrc 中添加如下,并保存. set termencoding=encodingset fileencodings=utf-8,gbk,ucs-bom,cp936set shif ...
- 人民币符号¥在css和html正确显示
商城项目需要涉及到人民币的页面现实问题.但是¥(指的是通常输入法中文全角模式下按shift+4的那个)在宋体(v3.03, v5.0)的情况下是显示一杠.常见的其他字体微软雅黑(Microsoft Y ...
- TalkingData游戏版本在Cocos2d-x 3.0使用
Cocos2dx在3.0的版本中改动确实不少啊,所以导致原来可以在Cocos2.x版本上的demo都不能直接用,所以不得不重要写一个新的demo 但是TalkingData的库一直都是可以用的,只是之 ...
- shell每日发邮件
LOGFILE="$fank/"`date +"%Y%m%d"`"data"#每日文件 from="abc@123.com&quo ...
- jquey复选框三级分类关联一二级分类
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Category_Manag ...
- RedHat9上安装jdk
1.先在windows下载jdk:jdk-6-dlj-linux-i586.bin 2.用ftp上传给linux下 3.chmod 777 jdk-6-dlj-linux-i586.bin 4.将jd ...
- Delphi-LowerCase 函数
函数名称 LowerCase 所在单元 System.SysUtils 函数原型 function LowerCase(const S: string): string; 函数功能 将字符串中所有的大 ...
- Java高精度学习第一弹
为了快速解决高精度问题,总算是要来接触java了,算上这学期要开java的课了,好好学习吧! 拿来练手的是hdu的1002,高精度加法. import java.util.*; import java ...
- CodeForces 478B 第六周比赛B题
B - B Time Limit:1000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u Descriptio ...