从应用角度看Android源码 - 研究一下Handler机制

xiaoxiao2021-02-28  127

上一篇扒开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; 略。。。。。。。 } 略。。。。。。 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的消息发送到接收全找到了。

 

 

 

 

 

 

 

转载请注明原文地址: https://www.6miu.com/read-22924.html

最新回复(0)