通信机制-Handler

本文详细阐述了Android消息驱动机制的核心概念,包括消息(Message)、消息队列(MessageQueue)、消息循环(Looper)和消息处理器(Handler),并介绍了它们在Android应用开发中的重要作用以及应用场景。同时,解释了Looper线程的创建、初始化过程,以及Handler类的初始化和消息处理流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

消息驱动机制主要涉及4个概念:

  1. 消息(Message)
  2. 消息队列(Message Queue)
  3. 消息循环(Looper)
  4. 消息处理器(Handler)
首先,为了实现消息驱动,Android基于Java的标准线程模型开发了Looper线程,Looper线程与标准线程的区别在于:Looper线程的run方法执行后不会马上退出,而是进入一个loop消息循环中等待消息的到来。
Looper线程的一般写法:
	class LooperThread extends Thread{
		public Handler mHandler;
		
		@Override
		public void run() {
			Looper.prepare();
			mHandler = new Handler(){

				@Override
				public void handleMessage(Message msg) {
					//…………
				}
				
			};
			Looper.loop();
		}
	}
Looper对象的创建是在Looper.prepare()中,这里值得注意的是:因为Looper对象创建之后会存入一个sThreadLocal的变量中,为了保证每个线程中只有一个唯一的Looper对象,在存入sThreadLocal变量之前,会对线程中是否已经存在一个Looper对象作判断,如果已经存在,会抛异常(Only one Looper may be created per thread),所以Looper.prepare()方法在当前线程中是不能多次调用的。
再看,Looper的主要作用是从消息队列里取消息用的,那么先得有个消息队列不是?看下Java层Looper对象的构造
 private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mRun = true;
        mThread = Thread.currentThread();
    }
在Looper的构造中,创建了MessageQueue对象,mRun表示当前线程处于Run状态,mThread存当前线程的引用。至于MessageQueue对象的初始化部分是通过JNI层实现的,C++不会,我也说不明白,就不写了。
那么再看看Handler吧,Handler是Looper线程的消息处理器,负责发送,处理的功能。初始化部分如下:
 public Handler(Callback callback, boolean async) {
        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());
            }
        }

        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 = callback;
        mAsynchronous = async;
    }
可以看到,Handler初始化的时候,会判断当前Handler类是不是匿名类,局部类,成员类啥的,如果是会给内存可能泄露的提示。另外Handler初始化的过程,主要做的是将之前本线程创建的Looper和MessageQueue关联到自己的成员变量中,这样三个就连在一起了。
最后一个Message,它里面有三个成员变量平时用得不多。When(表示消息将在什么时间执行 0表示立即);Next(用于表示下一条消息);sPool(成员变量用于表示消息池,每次调用obtain取出消息池头部的消息)
当一切Looper线程和Handler都初始化好之后,Looper.loop(),开始对MessageQueue进行无限循环的轮询,Loop方法主要的工作分四个部分:
  • 调用Binder.clearCallingIdentity ,记录并获取当前线程身份信息
  • 调用MessageQueue.next ,循环监听获取消息
  • 调用Message中Target成员变量的dispatchMessage,分发消息到处理器
  • 调用Message的recycle(),回收消息并更新消息池
当有消息要处理时,就是dispatchMessage调用后,该方法最多会做三次匹配工作,匹配成功后,将消息转发给相应的方法处理。匹配过程如下:
  1. 判断创建Message时,是否指定了回调方法,如果有就交给handleCallBack方法处理,一般POST组方法会指定Message的回调
  2. 判断创建Handler对象时,是否在构造中给该Handler对象指定了回调方法,如果有则调用回调方法中的handleMessage
  3. 如果以上都不满足,这直接调Handler中的handleMessage
消息处理完成后,需要将其回收并重新放到消息池中,这些由Message中的recycle方法完成,回收过程只是将成员变量清空,并没有回收消息对象本身,因此消息被回收后,不能直接操作该消息

目前我所知道的Handler的应用场景:
  1. 线程间的通信
  2. 更新UI
  3. 处理延时的任务

先写到这儿吧,后面再看看有什么需要补充说明的。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值