Handler消息机制(Java层)

本文详细介绍了Android的Handler消息机制,包括消息循环、消息发送和处理。Looper通过prepare和loop方法建立消息队列并进入无限循环,从MessageQueue中取出Message由Handler处理。Handler在构造时与Looper关联,用于发送和处理消息。文章通过源码分析阐述了整个消息传递流程。
摘要由CSDN通过智能技术生成

Handler消息机制(Java层)

1.简介

Android应用程序是通过消息来驱动的,系统为每一个应用程序维护了一个消息队列,应用程序的主线程不断地从这个消息队列中获取消息,然后就对这些消息进行处理,这样就实现了通过消息来驱动应用程序的执行。

通过消息驱动的好处是,消息的发送方只要把消息放在应用程序的消息队列中就行了,而不需要等待消息的接收方处理完整个消息才返回,这样就可以提高系统的并发性。

Hanlder与Looper之间的关系

各个元素的关系:

  • Runnable和Message可以被压入某个MessageQueue中,形成一个集合。
  • Looper循环地去做某件事情。
  • Handler是“处理事情的地方”。

一句话概括他们是:

Looper不断获取MessageQueue中的一个Message,然后由Handler来处理

就像中央处理器(Looper)不断从内存(MessageQueue)中读取指令(Message),执行指令(Handler),最终产生结果。

Looper负责创建一个MessageQueue,然后进入无限循环,不断从该MessageQueue中获取一个Message,将Message分发给对应的Handler处理。

Looper的主要作用:

  1. 与当前线程绑定,保证任何一个线程只有一个Looper实例,同时Looper也只有一个MessageQueue。
  2. Looper会不断从MessageQueue中去取消息,交给消息的target属性的dispatchMessage去处理。

与Windows应用程序的消息处理过程一样,Android应用程序的消息处理机制也是由消息循环消息发送消息处理这三部分组成。接下来将从源码的角度来分析这三个过程。

2.消息循环

在消息处理机制中,消息都是存放在一个消息队列中,而应用程序的主线程就是围绕这个消息队列进入一个无限循环的,直到应用程序退出。如果消息队列中有消息,应用程序的主线程就会把它取出来,并分发给相应的Handler进行处理;如果队列中没有消息,应用程序的主线程就会进入空闲等待状态,等待下一个消息的到来。消息的循环过程是有Looper类实现的,我们先看一下一个典型的Handler的用法:

class LooperThread extends Thread {
    public Handler mHandler;

    public void run() {
        Looper.prepare();//Looper的准备工作

        mHandler = new Handler() {//创建处理消息的Handler
            public void handleMessage(Message msg) {
                // process incoming messages here
            }
        };

        Looper.loop();//消息循环
    }
}
2.1 Looper.prepare()

首先从Looper.prepare()方法开始:
public static void prepare() {
prepare(true);
}

private static void prepare(boolean quitAllowed) {
    //ThreadLocal变量是每个线程独有的,可以用来判断是否已经创建过Looper了,保证每个线程只有一个Looper对象
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    //将新创建的Looper对象保存在ThreadLocal变量中
    sThreadLocal.set(new Looper(quitAllowed));
}

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();


private Looper(boolean quitAllowed) {
    mQueue = new MessageQueue(quitAllowed);//创建一个消息队列,按照先进先出的原则进出
    mThread = Thread.currentThread();//将当前线程保存在mThread变量中
}

可以看到,在Looper.prepare()方法中,创建了一个Looper对象,并将该Looper对象与当前线程进行关联了,保证一个线程只有一个Looper对象。同时在Looper中,创建了一个MessageQueue。这样的话,当前线程有一个Looper对象,Looper对象中又有一个MessageQueue。关系如下:currentThread->Looper->messageQueue。

MessageQueue的构造方法如下:

MessageQueue(boolean quitAllowed) {
    mQuitAllowed = quitAllowed;
    mPtr = nativeInit();//调用本地方法创建一个NativeMessageQueue
}

MessageQueue的初始化工作交由JNI方法nativeInit来实现了,它的主要工作是创建一个NativeMessageQueue,并把它保存在mPtr变量中。nativeInit方法的实现见Handler消息机制(Native)文章。

2.2 Handler的构建

接下来看Handler的创建:

//默认构造方法
public Handler() {
    this(null, false);
}
/*
 * Handler默认是同步的,除非async值为true。
 * 异步消息代表中断或者事件,不需要与同步消息一起排队。
 * 如果async为true,则handler会给每个Message或Runnable调用setAsynchronous(boolean)方法。
 */
public Handler(Callback callback, boolean async) {
    ....
    //获取Looper对象,该Looper对象是当前线程关联的Looper对象ÿ
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值