Handler,Lopper,Message,MessageQueue关系
来源:互联网 发布:淘宝网打不开 编辑:程序博客网 时间:2024/06/15 12:04
想了解他们的之间的关系,我们来分析一下系统Handler是如何工作的。
一、首先在ActivityThread.java中有一个main()方法,这是整个App的入口。
- ActivityThread 的初始化。
ActivityThread thread = new ActivityThread();
//里面饿加载一个系统H(Handler)
//敲黑板。划重点:四大组件等组件的启动和这个Handler密切相关。
//这里注意一点,就是为什么异常的时候Activity的生命周期不会被调用,很有可以就是这个Handler或者Looper已经挂了,肯定不会执行生命周期的其他方法。
thread.attach(false);//建立Binder通道 (创建新线程) - Lopper:消息循环器
Looper.prepareMainLooper();//和当前线程进行关联,初始化一个消息队列。
Looper.loop(); //开始进行循环
二:Handle简单分析
- 构造函数
Hanler的构造函数主要是两参和三参构造函数。
/** * @param callback 回调,在下面会讲到 * @param async 执行过程是否异步操作。默认是true */public Handler(Callback callback, boolean async) { ...... //获取当前线程的looper对象 mLooper = Looper.myLooper(); //在主线程是不需要创建Looper对象的,其他线程如果没有创建,需要调用Looper.prepare()创建 if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } //Handler和MessageQueue的关联是依靠Looper mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async;}/** * @param looper looper循环器 * @param callback 回调,在下面会讲到 * @param async 执行过程是否异步操作。默认是true */public Handler(Looper looper, Callback callback, boolean async) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async;}
发消息:
sendEmptyMessage(int what);
sendEmptyMessageDelayed(int what, long delayMillis);
sendEmptyMessageAtTime(int what, long uptimeMillis);
发空消息其实也是相当于在池中找了一个Message或者new了一个Message
Message msg = Message.obtain();
msg.what = what;
sendMessageDelayed(msg, delayMillis);处理消息:
分发消息
public void dispatchMessage(Message msg) {//msg.callback是Runable. if (msg.callback != null) { //代码块1,调用Runable里的run方法,常用于循环调用,请注意所在线程。 handleCallback(msg); } else { //在判断自己有没有回调。有回调就用自己的。 if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } //如果都没有,那么直接回调这个方法处理 handleMessage(msg); } }
//代码块,简单举例。 private Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { } }; private Runnable mRunnable = new Runnable() { @Override public void run() { mHandler.postDelayed(mRunnable,1000); } }; private void handlerRun(){ mHandler.post(mRunnable); } private void handlerRemove(){ mHandler.removeCallbacks(mRunnable); }
三 Looper简单分析:
- 看一下构造函数
private Looper(boolean quitAllowed) { //创建一个looper管理的消息队列 messageQueue。 //相当于给Looper消息循环器绑定一个MessageQueue mQueue = new MessageQueue(quitAllowed); //获得当前的线程 mThread = Thread.currentThread(); }
- 给Looper消息循环器绑定一个MessageQueue。Looper不断的从MessageQueue拿消息给主线程处理。这样的好处是当需要处理新的事件,只需要把消息放入MessageQueue中。
- ThreadLocal sThreadLocal = new ThreadLocal();线程安全作用,。起到桥梁的作用,把单独的Thread和Thread需要访问的Looper保存一份独立的副本ThreadLocal里面的ThreadLocalMap相当于hashMap,已当前线程为key,保存一个Looper。
- prepareMainLooper(),prepare()基本一样,前者是拿当前线程设置为主线程。prepare(boolean quitAllowed)只能调用一次,为了保证一个线程只有一个Looper存在。
loop(),从MessageQueue中不断的拿数据,并进行分发msg.target.dispatchMessage(msg);最后会回收消息 msg.recycleUnchecked();
来说说Looper.loop();死循环为什么不会卡死,其实当没有任务的时候系统是休眠了,主线程被阻塞在一个无限循环里了。looper维护了一个消息队列,如果队列里有消息就取出来执行,没有就休眠等待消息过来唤醒,
如果说出现过ANR之类的操作,也不是loop循环导致的,而是循环里的消息处理被阻塞。简单来收,当你一直循环在写各个科目的作业,如果作业写完了,你就可以睡觉,而在你写作业的过程中,你可以去吃饭,上厕所等其他操作。
四:MessageQueue。
- 在next()时。并不是在队头拿也就是不是依次拿,而是要进行比较:比较when时间,取合适的消息。
- 消息的回收:当handler把消息处理完成后。在looper的loop方法最后会对消息进行回收。
五:Message:
- 序列化的。
- 内部是一个消息池(链表队列)
//从池子里面拿,复用无用的。 //这样节省内存。而不是new Message();Message message = Message().obtain(); message .getTarget().sendEmptyMessage();
六:Handler和Looper关联
- 在Handler的构造函数中Looper.myLooper()获取当前线程所在的Looper。
- 如果在子线程中使用handler,需要先调用looper.prepare();,不然mLooper 是null,报异常。
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; mCallback = callback; mAsynchronous = async; }
最后总结、Handler,Looper,MessageQueue关系:
- handler负责发送Message或者Runable,Looper负责接收Handler发送的消息并放入MessageQueue,然后再把消息从MessageQueue取出回传到Handler。
- 一个Handler对应一个Looper,一个Looper对应一个MessageQueue,一个Handler可以产生多个Message。
- Handler相当于给外部线程的接口,用于线程间通信。Looper是由 系统支持的用于创建和管理MessageQueue的 依附于一个线程的循环对象,而Handler是用于操作线程內部的消息队列,所以Handler也必须依附一个线程。
- Handler,Lopper,Message,MessageQueue关系
- Message/MessageQueue/Handler/Looper之间到关系
- Handler Looper Message MessageQueue 的关系
- Message、Handler、MessageQueue、Looper之间的关系
- Handler MessageQueue Message Looper关系浅析
- Handler,Looper,Message,MessageQueue之间关系浅析
- Message,Handler,MessageQueue,Looper之间的关系
- Handler Looper Messagequeue Message 细节以及关系
- Handler,Looper,Message,MessageQueue的关系
- Message、Handler、MessageQueue、Looper之间的关系
- 详解Message,Handler,MessageQueue,Looper的关系
- Handler,Loop,Message,MessageQueue,ThreadLocal关系详解
- Lopper;Handler;Message--Runnable和Activity交互
- Looper,Handler,Message,MessageQueue
- Message,MessageQueue,Looper,Handler
- Message,Handler,Looper,MessageQueue
- Handler、Looper、MessageQueue、Message
- Handler,Message,Looper & MessageQueue
- Linux下安装Composer
- 【后缀数组】BZOJ1031(JSOI2007)[字符加密Cipher]题解
- 编写.gitignore文件时踩的坑
- 深度学习框架:tiny_dnn分析(2) ————分析sample代码
- android中使用Twitter登陆获取用户信息
- Handler,Lopper,Message,MessageQueue关系
- 浅析C语言的非局部跳转:setjmp和longjmp
- android7.x Launcher3源码解析(1)---启动流程
- RxJava之二——Single和Subject
- QT模态对话框与非模态对话框
- 方格取数 多线程动态规划
- Unity StartCoroutine 协同程序
- 实现底部导航栏中间凸起,(点击中间凸出按钮弹出菜单)
- 计蒜客 -- 求平方根