温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Android处理程序中Handler源码是什么

发布时间:2022-01-12 20:04:11 来源:亿速云 阅读:137 作者:iii 栏目:移动开发

今天小编给大家分享一下Android处理程序中Handler源码是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

线程Thread的线程变量ThreadLocal中,存放着这个线程的Looper;Looper在初始化时,会新建一个消息队列MessageQueue,之后Looper进入一个死循环,等待从消息队列MessageQueue取得消息Message(Looper是消费者),没有消息时会阻塞;

我们程序中的Handler,会通过sendMessage或post方法,往MessageQueue中添加消息时,添加的这个Message,会记录他是属于哪个Handler发出的,同时根据message.when,决定新添加的这个Message在Queue中的位置,MessageQueue中只有一个当前的Message,队列关系是通过Message中的prev,next维护的,Message是一个链表的节点;

添加消息后,消费者Looper取得Message,并调用建立Message的Hander的dispatchMessage方法。

咋一看好像Handler即sendMessage,又handlerMessage,事情还是只有一个线程在做事情。

但是后来想想,明白了这样设计的必要性。

因为这个***的线程一般而言,都是mainUI线程,如果你有个可以分成多个小任务的任务要处理,你没有使用Handler,直接执行,也许系统忙于处理你这个任务,而无法及时响应用户事件,从而导致ANR的抛出。

如果你把你的任务拆成几个小任务,用Handler来实现,那么系统就可以把你的小任务推到后面来处理,抽出时间来响应用户操作。

如果真的有大任务,一般式需要另外线程去处理,或者开启Service。

Android处理程序中Handler源码是什么

一个在新线程中使用handler例子,我们来分析下源码

Java代码

new Thread(new Runnable() { @Override public void run() { Handler handler; //1、初始化Looper Looper.prepare(); //2、绑定handler到CustomThread实例的Looper对象、定义处理消息的方法 handler= new Handler() { @Override public void handleMessage(Message msg) { } }; // 3、发送消息 handler.sendMessage(new Message()); handler.post(new Runnable()) handler.obtainMessage(1, "hello").sendToTarget(); //4、启动消息循环 Looper.loop(); } }).start();

1 Java代码

public static final void prepare() { if (sThreadLocal.get() != null) { // 每个线程,只能有一个Looper对象 throw new RuntimeException("Only one Looper may be created per thread"); } // 如果当前线程没有Looper,新建一个,构造函数是private的 sThreadLocal.set(new Looper()); } private Looper() { mQueue = new MessageQueue(); // 建立消息队列 mRun = true; mThread = Thread.currentThread(); }

2 Java代码

public Handler(){ mLooper = Looper.myLooper(); // 取得当前线程的Looper,如果抛异常 if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; // 取得消息队列 mCallback = null; }

3 Java代码

//不管调用哪个方法,最终执行的是 public boolean sendMessageAtTime(Message msg, long uptimeMillis){ boolean sent = false; // 取得消息队列 MessageQueue queue = mQueue; if (queue != null) { msg.target = this; // 消息发出着是自己 sent = queue.enqueueMessage(msg, uptimeMillis); // 添加到消息队列中 } else { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent; } final boolean enqueueMessage(Message msg, long when) { if (msg.when != 0) { throw new AndroidRuntimeException(msg + " This message is already in use."); } if (msg.target == null && !mQuitAllowed) { throw new RuntimeException("Main thread not allowed to quit"); } synchronized (this) { if (mQuiting) { RuntimeException e = new RuntimeException( msg.target + " sending message to a Handler on a dead thread"); Log.w("MessageQueue", e.getMessage(), e); return false; } else if (msg.target == null) { mQuiting = true; } msg.when = when; Message p = mMessages; // 之前没有其他消息了,MessageQueue中当前消息mMessages 就是传递进来的msg if (p == null || when == 0 || when < p.when) {  msg.next = p; mMessages = msg; this.notify(); // 唤醒  } else {  // 之前有其他消息了,将传递的msg放到适合的位置,根据when  Message prev = null;  while (p != null && p.when <= when) {  prev = p;  p = p.next;  }  msg.next = prev.next;  prev.next = msg;  this.notify(); // 唤醒  }  }  return true;  }

4 Java代码

public static final void loop() { Looper me = myLooper(); MessageQueue queue = me.mQueue; while (true) { // 死循环 Message msg = queue.next(); // 当队列中没有消息时会阻塞 if (msg != null) { if (msg.target == null) { // 消息没有发送者时,退出消息循环 // No target is a magic identifier for the quit message. return; } if (me.mLogging!= null) me.mLogging.println( ">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what ); // 调用消息发出者的dispatchMessage,这里msg.target是我们sendMessage的handler msg.target.dispatchMessage(msg); if (me.mLogging!= null) me.mLogging.println( "<<<<< Finished to " + msg.target + " " + msg.callback); msg.recycle(); } } } final Message next() { boolean tryIdle = true; while (true) { synchronized (this) { // 没有消息的或,会阻塞 try { if (mMessages != null) { if (mMessages.when-now > 0) { Binder.flushPendingCommands(); this.wait(mMessages.when-now); } } else { Binder.flushPendingCommands(); this.wait(); } } catch (InterruptedException e) { } } } }

以上就是“Android处理程序中Handler源码是什么”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI