handler looper message具体解析

本文深入解析Android中的消息处理机制,包括Looper、Handler和Message的核心作用及工作原理。介绍了Message的参数与构造方法,Looper如何创建并维持消息队列,以及Handler如何发送与处理消息。
 

android的消息处理有三个核心类:Looper,Handler和Message。其实还有一个Message Queue(消息队列),但是MQ被封装到Looper里面了

 

Android.os.Handler

相当于Activity 和runnable的之间的桥梁

android.os.Looper

作用主要是用来循环thread的message,通常调用是通过handler调用,循环message

android.os.Message

作用是提供两个int,一个object,能够被handle调用传值

下面详细讲讲

先讲Message

 Message 主要有6个参数,

public int what;

public int arg1;

public int arg2;

public Object obj;

Handler target;   

private static Message sPool;

我们通常调用的是如下方法

代码中是handler.obtainMessage();

查看handler源码,obtainMessage()方法

public final Message obtainMessage()
    {
        return Message.obtain(this);
    }

然后再跟踪,查看Message的obtain(Handler handler)方法如下

 public static Message obtain(Message orig) {
        Message m = obtain();
        m.what = orig.what;
        m.arg1 = orig.arg1;
        m.arg2 = orig.arg2;
        m.obj = orig.obj;
        m.replyTo = orig.replyTo;
        if (orig.data != null) {
            m.data = new Bundle(orig.data);
        }
        m.target = orig.target;
        m.callback = orig.callback;

        return m;
    }

Message方法中

 public void sendToTarget() {
        target.sendMessage(this);// this Message类型
    }

调用的是

 public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }

sendMessageDelayed调用的是

public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }

 

接下来讲Looper

Looper被设计用来使一个普通线程变成Looper线程。所谓Looper线程就是循环工作的线程。在程序开发中(尤其是GUI开发中),我们经常会需要一个线程不断循环,一旦有新任务则执行,执行完继续等待下一个任务,这就是Looper线程。

    final MessageQueue mQueue;
    Thread mThread;
    private Printer mLogging = null;
    private static Looper mMainLooper = null;

   private static final ThreadLocal sThreadLocal = new ThreadLocal();

(ThreadLocal 实现了线程存储,每一个线程都有自己独立的存储,所有的线程都共享ThreadLocal,但是每一个线程都有自己单独的values,并且每一个线程修改自己的        values 并不影响其它线程的values,values存的是线程的属性,类似活的线程数量,死的线程数量,大小等等)ThreadLocal 类中有个Values私有类

ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单:在ThreadLocal类中有一个Map,用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值对应线程的变量副本。

Looper中的prepare方法

public static final void prepare() {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper());
    }

set的就是values的变量。

prepare()背后的工作方式一目了然,其核心就是将looper对象定义为ThreadLocal

 private Looper() {
        mQueue = new MessageQueue();
        mRun = true;
        mThread = Thread.currentThread();
    }

Message的队列,通过looper循环message,message并不是直接加到messagequeue里面,而是通过handle加入的,可以通过Looper.myQueue()检索当前线程的MessageQueue

public static final Looper myLooper() {
        return (Looper)sThreadLocal.get();
    }

到此为止,你应该对Looper有了基本的了解,总结几点:

1.每个线程有且最多只能有一个Looper对象,它是一个ThreadLocal

2.Looper内部有一个消息队列,loop()方法调用后线程开始不断从队列中取出消息执行

3.Looper使一个线程变成Looper线程。

接下来讲Handler

handler扮演了往MQ上添加消息和处理消息的角色(只处理由自己发出的消息),即通知MQ它要执行一个任务(sendMessage),并在loop到自己的时候执行该任务(handleMessage),

里面有个接口

public interface Callback {

        public boolean handleMessage(Message msg);

    }

Handler中的常量

    final MessageQueue mQueue;

    final Looper mLooper;

    final Callback mCallback;

    IMessenger mMessenger;

Handler构造方法

public Handler(Looper looper) {

        mLooper = looper;

        mQueue = looper.mQueue;

        mCallback = null;

    }

public final Message obtainMessage()

    {

        return Message.obtain(this);

    }

就是我们刚才的message的方法

handle的post方法,给messagequeue发送消息

 public final boolean post(Runnable r)

    {

       return  sendMessageDelayed(getPostMessage(r), 0);

    }

 

public final boolean sendMessageDelayed(Message msg, long delayMillis)

    {

        if (delayMillis < 0) {

            delayMillis = 0;

        }

        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);

    }

public boolean sendMessageAtTime(Message msg, long uptimeMillis)

    {

        boolean sent = false;

        MessageQueue queue = mQueue;

        if (queue != null) {

            msg.target = this;

            sent = queue.enqueueMessage(msg, uptimeMillis); //该方法主要的任务就是把Message对象添加到MessageQueue中然后唤醒该线程

        }

        else {

            RuntimeException e = new RuntimeException(

                this + " sendMessageAtTime() called with no mQueue");

            Log.w("Looper", e.getMessage(), e);

        }

        return sent;

}

现在有疑问了,Message sendMessageDelayed 和handle的sendMessageDelayed两个方法有什么区别?

 

 

private final Message getPostMessage(Runnable r) {

        Message m = Message.obtain();

        m.callback = r;

        return m;

    }

 

接下来我们看一下HandleThread这个类

HandlerThread 继承Thread

三个参数

private int mPriority;      优先级

private int mTid = -1;      线程ID

private Looper mLooper;   当前Looper

 

public HandlerThread(String name) {

        super(name);

        mPriority = Process.THREAD_PRIORITY_DEFAULT; 默认为0 ,最大的值为19,表示不想执行该线程 -19-19

    }

将当前优先级设置为默认的0

HandlerThread完美地解决了myLooper可能为空的问题

//线程1调用getLooper来获得新线程的Looper 

    public Looper getLooper() {

        if (!isAlive()) {

            return null;

        }

        // If the thread has been started, wait until the looper has been created.

        synchronized (this) {

            while (isAlive() && mLooper == null) {

                try {

                    wait();     //如果新线程还未创建Looper,则等待

                } catch (InterruptedException e) {

                }

            }

        }

        return mLooper;

    }

 

 

//线程2

public void run() {

        mTid = Process.myTid();  //获取当前线程ID

        Looper.prepare();        //创建这个线程上的Looper

        synchronized (this) {

            mLooper = Looper.myLooper(); 

            notifyAll();        //通知取Looper的线程1,此时Looper已经创建好了

        }

        Process.setThreadPriority(mPriority);

        onLooperPrepared();

        Looper.loop();

        mTid = -1;

    }

 

 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值