Android之MessageQueue、Looper、Handler与消息循环
在android的activity中有各种各样的事件,而这些事件最终是转换为消息来处理的。android中的消息系统涉及到:
* 消息发送
* 消息队列
* 消息循环
* 消息分发
* 消息读取
消息对应的重要类有MessageQueue、Looper、Handler,它们分别对应着消息队列、消息循环和消息处理。
Handler类:
Handler主要用来发送消息和处理消息。每个handler实例都对应着一个线程和该线程的消息队列。
当你创建一个handler对象时,该handler对象就属于创建它的线程,并和该线程的消息队列绑定,比如在主线程中创建handler对象,那么该handler就只属于主线程,并且和主线程的消息队列绑定。(当然,每个线程都有自己的消息队列,在android中,消息队列是针对与线程的)。这样,该handler就可以发送消息到该消息队列并且处理该消息队列的消息了。
当执行一些费时的操作时,比如需要远程网络访问、下载等操作时,一般情况下都会启动一个新的线程去操作。而不会放在ui线程去做,这样可以防止android的5秒无相应导致的ANR异常。子线程中返回的结果怎样更新到ui线程呢,这时就可以通过handler来处理了。可以在主线程中定义handler,然后通过主线程handler把子线程中的消息发送到主线程对应的消息队列。在主线程中通过handler.handlerMessage就可以处理消息了,并更新到ui了。
我们刚才说过,Handler主要是用来发送、处理消息的。那么消息循环、队列是在哪里管理的。答案是:Looper、MessageQueue中。
Looper类:
looper类主要用来开启线程的消息循环。默认情况下,系统在启动的时候会为主线程创建消息循环。其他新创建的线程则没有,
如果需要,可以在该线程内调用Looper.prepare()来启用looper对象,然后调用Looper.loop()进入消息循环。
这样该线程就具有消息循环机制了,比如:
class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { // process incoming messages here } }; Looper.loop(); } }
实际上消息队列也是在Looper中创建的,看下Looper的loop()方法,这个方法就是用来做消息循环用的。
public static final void loop() { Looper me = myLooper(); //获得当前线程的Looper对象 MessageQueue queue = me.mQueue; //获得当前线程的消息队列 while (true) { //条件为true、一直循环执行。消息循环 Message msg = queue.next(); // might block //if (!me.mRun) { // break; //} if (msg != null) { if (msg.target == null) { // No target is a magic identifier for the quit message. return; } if (me.mLogging!= null) me.mLogging.println( ">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.whclearForRecycleat ); msg.target.dispatchMessage(msg); //消息分发 if (me.mLogging!= null) me.mLogging.println( "<<<<< Finished to " + msg.target + " " + msg.callback); msg.recycle(); //消息已经分发出去,对消息进行回收处理 } } }
我们再来看Handler的构造函数,在Handler的构造函数中获得当前线程的Looper对象、和消息队列。消息队列也是从looper中获得的,刚才我们说过。
public Handler() { if (FIND_POTENTIAL_LEAKS) { final Class<? extends Handler> klass = getClass(); if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0) { Log.w(TAG, "The following Handler class should be static or leaks might occur: " + klass.getCanonicalName()); } } //在Handler的构造函数中获得当前线程的Looper对象、和消息队列。消息队列也是从looper中获得的 mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = null; }
在handler中还有一些重要的方法:
handleMessage(Message) //处理消息
dispatchMessage(Message) //分发消息
sendMessage(Message) //发送消息
到这里我们大致可以了解android中的消息流程大概是这样的:
Handler获得当前线程的Looper、MessageQueue,并且发送消息到MessageQueue中。 Looper对消息做循环,并通过 msg.target.dispatchMessage来分发消息(target应该就是handler)。然后Handler.handlerMessage处理消息。
相关文章
- 聚焦 Android 11: 大功告成
- 基于chromium for android开发Android浏览器
- android 的hook技术,Android Native Hook技术(一)
- android开发笔记之 Android代码混淆打包
- 策略模式及Android源码中的应用
- android vlc 中文字幕,解决Android版vlc中文乱码问题
- android bioset 进程,kthrotlds(WatchDogs变种)查杀方法「建议收藏」
- android 定时器实例,Android定时器和Handler用法实例分析
- android短信验证码代码,Android短信验证码自动填写实现代码
- Android n_android 反编译
- Android保存图片到相册(适配android 10以下及以上)
- android studio输出文字_androiditem长按删除
- android 系统浏览器 源码-Android 最最最简单的浏览器代码
- Android的TabLayout未铺满如何解决
- 【Android RTMP】RTMPDumb 源码导入 Android Studio ( 交叉编译 | 配置 CMakeList.txt 构建脚本 )
- 【Android 异步操作】手写 Handler ( 循环者 Looper | Looper 初始化 | Looper 遍历消息队列 MessageQueue )
- 谷歌大量删除 Android 开源项目中 Fuchsia 相关代码
- 【错误记录】Android Studio 编译报错 ( Could not find com.android.tools.build:gradle:4.2.1. )
- 【错误记录】未安装该应用 ( 在 Android 12 之后 组件设置 android:exported=“false“ 属性 )
- Android版本检测更新详解手机开发
- [android] ndk环境的搭建详解手机开发
- 16年前,谷歌为何花5000万美元买下Android?
- Android系统自带样式(android:theme)
- Android左右滑出菜单实例分析
- android新建草稿删除后下次开机还会显示保存的草稿
- android通过代码的形式来实现应用程序的方法