Android消息处理机制1——Handler

Android消息处理机制系列文章整体内容如下

Android消息处理机制1——Handler
Android消息处理机制2——Message
Android消息处理机制3——MessageQueue
Android消息处理机制4——Looper

一 构造器

Handler的构造器有7种

1、public Handler()
2、public Handler(Callback callback)
3、public Handler(boolean async)
4、public Handler(Callback callback, boolean async){
        //代码省略
        mLooper = Looper.myLooper(); //会返回一个自己线程绑定的Looper,如果当前线程没有绑定Looper,就会返回null。
        mQueue = mLooper.mQueue; //获取looper维护的queen队列
        mCallback = callback; 
         //代码省略
}

5、public Handler(Looper looper, Callback callback)
6、public Handler(Looper looper)
7、public Handler(Looper looper, Callback callback, boolean async){
        mLooper = looper;//可以绑定其他的looper实例
        mQueue = looper.mQueue;  //获取looper维护的queen队列
        mCallback = callback;    
}

使用编号为1、2、3的构造器创建handler实例,最终调用的构造器都是编号为4的构造器。
这个handler实例只能持有它所在线程的looper对象的引用

如果使用编号为5、6的构造器,最终调用的构造器是编号为7的构造器。它可以持有任意线程的looper对象的引用。

二 发送消息

消息发送有两个步骤:

  1. 构建message对象
  2. 将message发送到消息队列里面去

1、构建Message对象

将消息抽象成Message类,里面比较重要的属性有:

public int what; //用户定义的消息编码,让接收者能区分不同的消息,从而做出不同的处理
public int arg1; //int类型的数据
public int arg2; //int类型的数据
public Object obj; //任意类型的数据 是否把所有的obj都自动转化为Parcelable类型数据,obj也可以用来标识message,postAtTime(Runnable r, Object token, long uptimeMillis)方法就是用obj来标识message的
Handler target; //处理返回的message的handler实例
Runnable callback; //消息被处理的时候执行被执行的回调

下面的obtainMessage方法都会调用Message的obtain方法,会组装一个message对象。

public final Message obtainMessage()
public final Message obtainMessage(int what)
public final Message obtainMessage(int what, Object obj)
public final Message obtainMessage(int what, int arg1, int arg2)
public final Message obtainMessage(int what, int arg1, int arg2, Object obj)

2、将message发送到消息队列

public final boolean post(Runnable r)
public final boolean postAtTime(Runnable r, long uptimeMillis)
public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)
public final boolean postDelayed(Runnable r, long delayMillis)

上面四个postXX方法会先调用getPostMessage(Runnable r) 方法,将runnable封装成message。具体实现如下

private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r; 
        return m;
    }

组装的message没有what属性,也就没有办法针对不同的message采用不同的处理方法。

然后会调用下面的方法发送消息

    public final boolean sendMessage(Message msg)
    public final boolean sendMessageDelayed(Message msg, long delayMillis)
    
   //下面三个方法会在方法内部组装一个 message
    public final boolean sendEmptyMessage(int what)
    public final boolean sendEmptyMessageDelayed(int what, long delayMillis)
    public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis)   

上面的5个发送message的方法最终都会调用sendMessageAtTime方法

public boolean sendMessageAtTime(Message msg, long uptimeMillis){
    MessageQueue queue = mQueue; //在构造handler对象的时候获取的, looper管理的消息队列
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
}
public final boolean postAtFrontOfQueue(Runnable r)

会调用

public final boolean sendMessageAtFrontOfQueue(Message msg)

sendMessageAtFrontOfQueue这个方法其实就是将sendMessageAtTime的uptimeMillis设置为0

    public final boolean sendMessageAtFrontOfQueue(Message msg) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        return enqueueMessage(queue, msg, 0); 
    }

上面的所有发送消息的方法最终都会调用私有方法enqueueMessage(queue, msg, uptimeMillis),enqueueMessage又会调用MessageQueue的boolean enqueueMessage(Message msg, long when),将消息放入消息队列。

三 删除消息

public final void removeCallbacks(Runnable r) //根据runnable删除message
public final void removeCallbacks(Runnable r, Object token) //根据runnable和obj删除message,token最终会被组装成 message的obj属性
public final void removeMessages(int what) //根据what删除相关的message
public final void removeMessages(int what, Object object) //根据what和object删除相关的message
public final void removeCallbacksAndMessages(Object token) // 根据obj删除没有被处理的message,如果 token为null则会删除所有的message。

四 处理事件

由dispatchMessage根据message是否含有callback来将message交由handleCallback或者handleMessage来处理

public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            //如果是调用postXX发送的消息则会执行handleCallback,handleCallback是私有方法,并且已经由handler实现了,用户不需要自己实现handleCallback方法
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                //如果mCallback不为空,则执行mCallback的具体实现类里的handleMessage方法
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            //使用handler自己的handleMessage方法
            handleMessage(msg);
        }
    }

dispatchMessage是在looper的loop()方法中调用的,用来分发message。

public static void loop(){
    //省略代码
    for(;;){
    try {
                msg.target.dispatchMessage(msg);
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }
    }
    //省略代码
}

(完)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,980评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,422评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,130评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,553评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,408评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,326评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,720评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,373评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,678评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,722评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,486评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,335评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,738评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,283评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,692评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,893评论 2 335