扒开AsyncTask的祖坟的时候提到了Handler,说白了AsyncTask只是对Handler进行了封装,这次就进一步研究一下Handler机制,

上一篇扒开AsyncTask的祖坟的时候提到了Handler,说白了AsyncTask只是对Handler进行了封装,这次就进一步研究一下Handler机制,我写了个模拟handler机制的Demo (https://github.com/wk415190639/Looper),提及handler必然涉及到Looper、Message、MessageQueue,这几个类Handler机制主要组成部分,先分析一下这个Demo

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        new ReceiveThread().start();
        startActivity(new Intent(this,WorkActivity.class));
    }
}

MainActivity 里做了两件事,第一是开启了模拟的UI线程,第二就是开启WorkActivity,简单到极致,没什么可说的了,看看WorkActivity里面做了什么

public class WorkActivity extends Activity  implements View.OnClickListener {

    HandlerTest handlerTest = new HandlerTest() {
        @Override
        public void handleMessage(MessageTest msg) {
            super.handleMessage(msg);
            Log.i("QueueTest", Thread.currentThread().getName() + " : handleMessage : " + msg.msg);
        }
    };
    int i = 100;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Thread.currentThread().setName("workThread");
        setContentView(R.layout.activity_main);
        findViewById(R.id.button).setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        MessageTest msg = new MessageTest();
        msg.msg = i++;
        Log.i("QueueTest", Thread.currentThread().getName() + " : sendMessage : " + msg.msg);
        handlerTest.sendMessage(msg);
    }
}
WorkActivity 里面先以匿名内部类的方式实例化一个HandlerTest类,这和平时我们获取handler的方式一样。在OnCreate()回调里将当前的线程名设置为workThread,这个线程原本为真正的UI线程,为了Demo的演示效果就把Android原本的UI线程和工作线程兑换了名字。接着注册了Button的点击事件,在Button的onClicks事件里发送消息。也就是让HandlerTest把消息放进消息队列。HandlerTest类也是非常简单的。

public class HandlerTest {
    public LinkedBlockingDeque linkedBlockingDeque;

    public HandlerTest() {

        linkedBlockingDeque = LooperTest.myLooper().queue;
    }

    public void handleMessage(MessageTest msg) {

    }

    public void dispatchMessage(MessageTest msg) {
        handleMessage(msg);

    }

    public final boolean sendMessage(MessageTest msg) {

        msg.target = this;
        linkedBlockingDeque.offer(msg);
        return true;
    }

}


在handlerTest类里有三个方法sendMessage是写给工作线程通过handler调用的,这个函数主要是把Message放进了消息队列linkedBlockingDeque里,这个linkedBlockingDeque是在handlertest类构造函数里赋值的,dispatchMessage函数也是主要是为了调用handleMessage函数,可以看到handleMessage函数里是空的,他的逻辑是在WorkActivity里以匿名内部类t的方式被复写的。所以真正的逻辑是在workActivity.java里,再去看看linkedBlockingDeque的真正位置LooperTest里都做了什么


public class LooperTest {

    public LinkedBlockingDeque<MessageTest> queue;
    public Thread thread;
    private static LooperTest looperTest;
    public LooperTest() {
        queue = new LinkedBlockingDeque<MessageTest>();
        thread = Thread.currentThread();
    }
    public static void prepareMainLooper() {
        if (looperTest == null)
            looperTest = new LooperTest();
    }

    public static @Nullable LooperTest myLooper() {
        return looperTest;
    }
    
    public void loop() {

        for (; ; ) {
            try {
                Log.i("QueueTest", Thread.currentThread().getName() + " : start blocking....................");
                MessageTest msg = (MessageTest) queue.take();
                msg.target.dispatchMessage(msg);
                Log.i("QueueTest", Thread.currentThread().getName() + " : read msg : " + msg.msg + "\n\n ");

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

}

LooperTest 在构造函数中实例化的一个消息队列,prepareMainLooper()实例化了LooperTest,myLooper()返回LooperTest实例,Loop()就是循环读取消息队列里面的数据,当消息队列为空时会一直阻塞在哪里,直到读取到消息队列中的数据,接着调用HandlerTest的dispatchMessage()方法,在dispatchMessage()调用handleMessage(),这样WorkActivity$HandlerTest 的handleMessage()就被调用了,因为是在LooperTest所在线程调用的,所以handleMessage()会运行在LooperTest所在的线程里,也就是最开始MainActivity开启的那个ReceiveThread线程,如果他是UI线程,那么handleMessage()就会运行在UI线程了。在回过来看一看在最开始的是开启的那个线程都做什么工作


public class ReceiveThread extends Thread {

    public ReceiveThread() {
        setName("ReceiveThread");
    }

    @Override
    public void run() {
        LooperTest.prepareMainLooper();
        LooperTest looperTest = LooperTest.myLooper();
        looperTest.loop();
    }
}

这个类主要的工作就是实例化了Looper,然后让Looper循环读取消息队列的消息,再将消息发给HandlerTest。下面送一张蜘蛛网图和点击一次的效果


I/QueueTest: ReceiveThread : start blocking....................
I/QueueTest: workThread : sendMessage : 100
I/QueueTest: ReceiveThread : handleMessage : 100
I/QueueTest: ReceiveThread : read msg : 100
             
              
I/QueueTest: ReceiveThread : start blocking....................

接下来看看Android源码吧

先从Handler看看吧

   Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
    };

这里边看似平常却暗藏玄机,去Handler的构造函数看一下
public Handler() {   this(null, false); }

 public Handler(Callback callback, boolean async) {
       
 	略。。。。。。
        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        略。。。。。。。
    }

代码里略掉了一些无关部分,构造函数里主要是获取了所在线程的Looper实例和Looper实例下的mQueue消息队列。主线程的Looper是在ActivityThread的main方法里被实例化的(下次研究一下Looper如何在ActivityThread里实例化的),ActivityThread 就相当于Demo里写的ReceiveThread的那个类,这里先不做研究。再handler是如何发送消息的,一般我们会调用sendMessage(Message msg),那就进去看看他的实现

   public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 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) {
        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, uptimeMillis);
    }

 private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }
跟到这里可以发现Message实例的成员target被赋值为当前的handler实例,然后就把msg推进了消息队列里面,到这里消息的发送就结束了,那在去看看消息再UI线程里是怎么接收的吧,像Demo里所写的那样,Message 是在Looper 类的loop()函数里被接收的,那就跳进去看看,

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

        for (;;) {
               Message msg = queue.next(); // might block
               msg.target.dispatchMessage(msg);
        }
    }
删去了一些碍眼的代码,就剩下这几句骨干了,loop()里循环读取queueu里的数据,读到数据消息后调用message的成员对象target(也就是handler)的dispatchMessage(msg)方法,将收到的消息分发出去

 public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

在这里边调用了   handleMessage(msg),之后再上面写的匿名内部类(new Handler(){})的handleMessage()里就能接收到消息了。到这里handler的消息发送到接收全找到了。



猜你喜欢

转载自blog.csdn.net/w1143408997/article/details/76714129
今日推荐