从应用角度看Android源码
来源:互联网 发布:淘宝加密算法 编辑:程序博客网 时间:2024/05/26 08:41
上一篇扒开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 : 100I/QueueTest: ReceiveThread : handleMessage : 100I/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的消息发送到接收全找到了。
- 从应用角度看Android源码
- 从应用角度看Android源码
- 从应用角度看Android源码
- 从应用角度看Android源码
- 从应用角度看Android源码
- 【Android】从源码角度看Handler机制
- 从源码角度看Handler原理
- 从源码角度看Activity知识点(一)
- 从源码角度看Activity知识点(二)
- 从JDK源码角度看Boolean
- 从JDK源码角度看Object
- 从JDK源码角度看Byte
- 从JDK源码角度看Short
- 从JDK源码角度看Integer
- 从JDK源码角度看Long
- 从JDK源码角度看Long
- 从JDK源码角度看Float
- 从JDK源码角度看Float
- liunx访问谷歌
- 关于mybatis的模糊查询
- tensorflow:使用tfrecords时的注意事项
- 习题 3.7 设圆半径r=1.5,圆柱高h=3,求圆周长、圆面积、圆球表面积、圆球体积、圆柱体积。
- re.match与re.search的区别
- 从应用角度看Android源码
- 简单选择排序-->堆排序
- Face Detection(2)
- 不定宽高水平且垂直居中的实现方法
- Java并发工具类
- 【笔记】maven构建多模块项目
- ubuntu中的sudoers文件损坏,修复办法(附图、详细)
- HTML五类方法实现页面跳转
- java-Iterator(迭代器)遍历集合