Handler消息机制源码解析

Handler消息机制源码解析

handler机制原理

 handler发送Message 唤醒Looper器,轮询器开始遍历MessageQueue,轮询取消息,处理消息

学习一项新技术时,可以从源头入手,按流程走,按着代码走向剖析源码。

Message

从API的角度上来看有以下三种,推荐用(2)、(3)种,因为它们本质是从消息池里取消息,

(1)Message msg = new Message();

(2)Message msg = Message.obtain();

     public static Message obtain() {
        synchronized (sPoolSync) {
            if (sPool != null) {
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                sPoolSize--;
                return m;
            }
        }

        return new Message();
    }
    方法重载很多,但每个方法本质都会走上面的代码
//
 handler.sendMessage(msg);
//handler已经绑定
(3)Message msg = handler.obtainMessage();
msg.sendToTarget();

Looper(轮询器)

* ActivityThread类中初始化,应用程序运行之前执行,main方法如下:

 //主线程
 public static final void main(String[] args) {
    。。。
    //轮询器的初始化
    Looper.prepareMainLooper();

    。。。
    //轮询器开始取消息
    Looper.loop();


}

*loop方法

  public static final void loop() {
    Looper me = myLooper();
    MessageQueue queue = me.mQueue;

    while (true) {
        //没有消息阻塞
        Message msg = queue.next(); // might block

        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.what
                    );
            msg.target.dispatchMessage(msg);
            if (me.mLogging!= null) me.mLogging.println(
                    "<<<<< Finished to    " + msg.target + " "
                    + msg.callback);

            // Make sure that during the course of dispatching the
            // identity of the thread wasn't corrupted.
            final long newIdent = Binder.clearCallingIdentity();
            if (ident != newIdent) {
                Log.wtf("Looper", "Thread identity changed from 0x"
                        + Long.toHexString(ident) + " to 0x"
                        + Long.toHexString(newIdent) + " while dispatching to "
                        + msg.target.getClass().getName() + " "
                        + msg.callback + " what=" + msg.what);
            }

            msg.recycle();
        }
    }
}

Handler(原名)

Hander的初始化

 //程序员写的代码
   Handler handler = new Handler(){
        public void handleMessage(Message msg){
        }
   }

   //handler的默认构造函数
    public Handler() {
        。。。
        //取出轮询器,轮询取消息
        mLooper = Looper.myLooper();
        。。。
        //消息队列,存放handler发的消息
        mQueue = mLooper.mQueue;

        mCallback = null;
    }

发消息

1、Message类的sendToTarget public void sendToTarget() { 本质还是调用2的发消息方法,target即handler,this即msg。 target.sendMessage(this); }

 2、 //1.发消息 handler.sendMessage(msg);//发消息

public final boolean sendMessage(Message msg)
{
    //2 sendMessageDelayed 即时消息
    return sendMessageDelayed(msg, 0);
}

//2 sendMessageDelayed,参数消息、延时值

public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
    if (delayMillis < 0) {
        delayMillis = 0;
    }
    //3 sendMessageAtTime  加上当前时间来判断
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}

//3 sendMessageAtTime
public boolean sendMessageAtTime(Message msg, long uptimeMillis)
{
    boolean sent = false;
    //this 就是 handler mQueue 就是从Looper中取出来的消息队列
    MessageQueue queue = mQueue;
    if (queue != null) {
        //handler发消息 把当前的handler对象绑定到Message对象中
        msg.target = this;
        // 把消息放到消息队列里,按时间排序 ,如果你调用sendMessage(msg),uptimeMillis = 0
        //4 enqueueMessage
        sent = queue.enqueueMessage(msg, uptimeMillis);
    }
    。。。
    return sent;
}

 //4 enqueueMessage

final boolean enqueueMessage(Message msg, long when) {


    final boolean needWake;
    synchronized (this) {
        if (mQuiting) {
            RuntimeException e = new RuntimeException(
                msg.target + " sending message to a Handler on a dead thread");
            Log.w("MessageQueue", e.getMessage(), e);
            return false;
        } else if (msg.target == null) {
            mQuiting = true;
        }

        msg.when = when;//Message的发送时间
        //Log.d("MessageQueue", "Enqueing: " + msg);
        //mMessages 是MessageQueue对象里的属性
        Message p = mMessages;
        if (p == null || when == 0 || when < p.when) {
           //msg 发的消息
            msg.next = p;
            mMessages = msg;
            needWake = mBlocked; // new head, might need to wake up
        } else {
            //消息插入的位置
            Message prev = null;
            while (p != null && p.when <= when) {
                prev = p;
                p = p.next;
            }
            msg.next = prev.next;
            prev.next = msg;
            needWake = false; // still waiting on head, no need to wake up
        }
    }
    if (needWake) {
        nativeWake(mPtr);//jni
    }
    return true;
}

取消息

public static final void loop() {
    Looper me = myLooper();
    //从轮询器中获取消息队列的Handler的queue是同一个消息队列
    MessageQueue queue = me.mQueue;

    while (true) {
        //没有消息阻塞
        //从消息队列里取消息头
        Message msg = queue.next(); // might block

        if (msg != null) {

            ...
             打印日志
            。。。
           处理消息
            msg.target.dispatchMessage(msg);
            。。
            回收消息,首先清空消息的属性,然后再把消息放到消息池
            2.3版本代码功能和结构都有些问题,高版本进行了优化,添加了sPoolSize++
            msg.recycle();

        }
    }
}

  处理消息
  msg.target.dispatchMessage(msg);

public void dispatchMessage(Message msg) {
    if (msg.callback != null) {//runOu......
        //处理runOnUithread方法
       //1
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        //调用handleMessage 主线程
        handleMessage(msg);
    }
}
//1.
  handleCallback(msg);

//2.
private final void handleCallback(Message message) {
    message.callback.run();//runnable 跟线程没关系
}

runOnUiThread的原理

public final void runOnUiThread(Runnable action) {
    if (Thread.currentThread() != mUiThread) {
        //1, mHandler.post(action);
        mHandler.post(action);
    } else {
        action.run();
    }
}

//1. mHandler.post(action);
  public final boolean post(Runnable r)
{
    //2.sendMessageDelayed
   return  sendMessageDelayed(getPostMessage(r), 0);
}

//2.sendMessageDelayed
 public final boolean post(Runnable r)
{
   3.getPostMessage(r)
   return  sendMessageDelayed(getPostMessage(r), 0);
}
//3getPostMessage(r)
 private final Message getPostMessage(Runnable r) {
    Message m = Message.obtain();
    m.callback = r;
    return m;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值