博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Handler源码分析
阅读量:3932 次
发布时间:2019-05-23

本文共 8984 字,大约阅读时间需要 29 分钟。

一、Handler的创建

Handler的创建会关联一个Looper对象,而Looper对象关联着MessageQueen对象,所以在Handler创建时,取出LooperMessageQueen

public Handler(Callback callback, boolean async) {
... //取出Looper mLooper = Looper.myLooper(); if (mLooper == null) {
throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } //取出Looper中的MessageQueen mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async;}

Looper是存放在ThreadLocal里面的,可以看下面的源码

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

整个创建的过程就完了,这里做了哪几件事:

  • 取出Looper
  • 取出Looper中的MessageQueen

二、Handler发送消息

1、方式一:sendMessage(Message msg)

public final boolean sendEmptyMessage(int what){
return sendEmptyMessageDelayed(what, 0);}//往下追踪public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
Message msg = Message.obtain(); msg.what = what; return sendMessageDelayed(msg, delayMillis);}//往下追踪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 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);}//调用sendMessage方法其实最后是调用了enqueueMessage方法private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
//为msg.target赋值为this,也就是把当前的handler作为msg的target属性 //如果大家还记得Looper的loop()方法会取出每个msg然后执行msg.target.dispatchMessage(msg)去处理消息,其实就是派发给相应的Handler msg.target = this; if (mAsynchronous) {
msg.setAsynchronous(true); } //最终调用queue的enqueueMessage的方法,也就是说handler发出的消息,最终会保存到消息队列中去 return queue.enqueueMessage(msg, uptimeMillis);}

2、方式二:post(Ruunable r)

public final boolean post(Runnable r){
return sendMessageDelayed(getPostMessage(r), 0);}

其实post()方法最终也会保存到消息队列中去,和上面不同的是它传进来的一个Runnable对象,执行了getPostMessage()方法,我们往下追踪

private static Message getPostMessage(Runnable r) {
Message m = Message.obtain(); m.callback = r; return m;}

实质上就是将这个Runnable保存在Message的变量中,这就导致了我们下面处理消息的时候有两种不同方案

三、Handler处理消息

你还记得前面所说Loopermsg.target.dispatchMessage()方法吗?这个方法就是调用HandlerdispatchMessage()

public void dispatchMessage(Message msg) {
if (msg.callback != null) {
//1. post()方法的处理方法 handleCallback(msg); } else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return; } } //2. sendMessage()方法的处理方法 handleMessage(msg); }}//1. post()方法的最终处理方法private static void handleCallback(Message message) {
message.callback.run();}//2. sendMessage()方法的最终处理方法public void handleMessage(Message msg) {
}

整个处理的过程就完了,这里做了哪几件事:

  • post()方法的处理方法就是将传进来的Runnable执行run()方法
  • sendMessage()方法的处理方法就是执行handleMessage()空方法,这也是我们为什么要在Handler重写这个方法的原因

三、Handler 的post(Runnable)和handleMesaage的用法

1).post(Runnable)用法:

package mountain_hua.learn_handler1; import android.os.Handler;import android.support.v7.app.AppCompatActivity;import android.os.Bundle; public class MainActivity extends AppCompatActivity {
//先在主线程中创建Handler,Handler会自动与主线程绑定 private Handler handler=new Handler(); @Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); System.out.println("main thread id " + Thread.currentThread().getId()); test_handmessage(); } public void test_handmessage(){
new Thread(){
@Override public void run(){
//处理信息 try{
//模拟费时操作 System.out.println("run thread id " + Thread.currentThread().getId()); sleep(1000); //这里使用Runnable Runnable runnable=new Runnable() {
@Override public void run() {
System.out.println("Runnable thread id " + Thread.currentThread().getId()); } }; //这里执行post(Runnable)操作 handler.post(runnable); }catch (Exception e){
e.printStackTrace(); } } }.start(); } }

首先在主线程中创建了一个handler,这时handler会自动绑定主线程,然后在一个新线程里面创建了Runnable对象,并且用了handler的post(Runnable)操作来发送消息给在主线程中的handler执行。我们看看打印出来的结果:

07-30 21:34:23.891 21509-21509/mountain_hua.learn_handler1 I/System.out: main thread id 107-30 21:34:23.893 21509-21560/mountain_hua.learn_handler1 I/System.out: run thread id 937807-30 21:34:24.894 21509-21509/mountain_hua.learn_handler1 I/System.out: Runnable thread id 1

结果可以看到Runnable与main线程id相同,说明了Runnable里面执行的事件是被handler放在主线程中执行的,与Run所在线程无关 。

2).handleMessage用法:

package mountain_hua.learn_handler1; import android.os.Handler;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.os.Bundle; public class MainActivity extends AppCompatActivity {
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); test_handmessage(); test_handmessage1(); } public void test_handmessage(){
new Thread(){
@Override public void run(){
//处理信息 try{
//模拟费时操作 System.out.println("run thread id " + Thread.currentThread().getId()); sleep(1000); }catch (Exception e){
e.printStackTrace(); } Message msg=new Message(); // 也可以用下面两种方法获得Message // Message msg1=Message.obtain(); // Message msg2=handler.obtainMessage(); msg.what=0;//msg.what的类型是int型,作为msg的识别码 msg.arg1=1;//msg.arg1的类型是int型,可以传递简单的参数 msg.arg2=2;//msg.arg2的类型是int型,可以传递简单的参数 msg.obj="Object类型";//msg.obj是Object型,可以传递任意参数 //将Message发送给handler handler.sendMessage(msg); } }.start(); } public void test_handmessage1(){
new Thread(){
@Override public void run(){
//处理信息 try{
//模拟费时操作 System.out.println("run thread id " + Thread.currentThread().getId()); sleep(2000); }catch (Exception e){
e.printStackTrace(); } Message msg=new Message(); // 也可以用下面两种方法获得Message // Message msg1=Message.obtain(); // Message msg2=handler.obtainMessage(); msg.what=99;//msg.what的类型是int型,作为msg的识别码 msg.arg1=100;//msg.arg1的类型是int型,可以传递简单的参数 msg.arg2=101;//msg.arg2的类型是int型,可以传递简单的参数 msg.obj="Object类型";//msg.obj是Object型,可以传递任意参数 //将Message发送给handler handler.sendMessage(msg); } }.start(); } Handler handler=new Handler() {
@Override public void handleMessage(Message msg) {
switch (msg.what) {
case 0: System.out.println("handleMessage thread id " + Thread.currentThread().getId()); System.out.println("msg.arg1:" + msg.arg1); System.out.println("msg.arg2:" + msg.arg2); break; case 99: System.out.println("handleMessage thread id " + Thread.currentThread().getId()); System.out.println("msg.arg1:" + msg.arg1); System.out.println("msg.arg2:" + msg.arg2); } } };}

这里用两个Messge给主线程中的Handler发送消息,打印出的信息为:

07-30 21:19:08.532 2461-2782/mountain_hua.learn_handler1 I/System.out: run thread id 931107-30 21:19:08.532 2461-2783/mountain_hua.learn_handler1 I/System.out: run thread id 931207-30 21:19:09.532 2461-2461/mountain_hua.learn_handler1 I/System.out: handleMessage thread id 107-30 21:19:09.532 2461-2461/mountain_hua.learn_handler1 I/System.out: msg.arg1:107-30 21:19:09.532 2461-2461/mountain_hua.learn_handler1 I/System.out: msg.arg2:207-30 21:19:10.532 2461-2461/mountain_hua.learn_handler1 I/System.out: handleMessage thread id 107-30 21:19:10.532 2461-2461/mountain_hua.learn_handler1 I/System.out: msg.arg1:10007-30 21:19:10.532 2461-2461/mountain_hua.learn_handler1 I/System.out: msg.arg2:101

可以看到handler处理消息队列是在主线程中处理的(handler在哪个线程中创建的就与哪个线程绑定), 与run存在的线程无关。

参考:

转载地址:http://hjqgn.baihongyu.com/

你可能感兴趣的文章
rails 导出 excel
查看>>
rails 路由设置
查看>>
Ruby on Rails命令
查看>>
ruby的数组操作
查看>>
git 常用命令
查看>>
查看历史 -Git日志
查看>>
git使用总结
查看>>
rails过滤html
查看>>
rails过滤器
查看>>
layout详解
查看>>
hadoop + zookeeper 安装部署
查看>>
rake应用
查看>>
opera插件开发
查看>>
2012工作日志
查看>>
MongoDB基本介绍及一些用法
查看>>
hash对象
查看>>
基本数据类型和对象
查看>>
mongoDB应用
查看>>
MongoDB 和 MongoMapper的示例用法简介
查看>>
欢迎使用CSDN-markdown编辑器
查看>>