Looper源码细说
来源:互联网 发布:四川广电网络投诉电话 编辑:程序博客网 时间:2024/06/11 17:00
Looper作为引擎般的存在,主要作用是维持一个死循环,一旦有消息到来就通知handler分发事件。
Looper的创建
//线程中初始化 获取Looper public static void prepare() { prepare(true); } private static void prepare(boolean quitAllowed) {//sThreadLocal 存放线程的局部变量 每个线程拿到一个原始变量的副本进行操作//在这里就是为每个线程存放一个Looper对象,如果已经存在 则报异常 if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); }//sThreadLocal 存放线程的局部变量 每个线程拿到一个原始变量的副本进行操作//多了一个quitAllowed 默认是true 主线程赋值false表示looper不可退出 sThreadLocal.set(new Looper(quitAllowed)); }//主线程初始化Looper的地方 在MainThread的main方法里面调用 这也是主线程里面不用调prepare的原因 public static void prepareMainLooper() { prepare(false);//下面是主线程多出来的部分 就是单独的为主线程的Looper设置一个线程局部变量sMainLooper synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); }//myLooper() 方法里就一句话 return sThreadLocal.get(); 最终拿到线程sThreadLocal sMainLooper = myLooper(); } }....//上面 进过prepare 最终new一个Looper对象//同时拿到MessageQueue和创建宿主线程thread; private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
Looper的退出
public void quit() { mQueue.quit(false); } public void quitSafely() { mQueue.quit(true); }
上面简短的代码可以看出 其调用的是成员变量MessageQueue的退出方法 那我们就跟进看一看
MessageQueue中的代码
void quit(boolean safe) {//mQuitAllowed 主线程调用prepare时传false 不允许在主线程中退出循环 if (!mQuitAllowed) { throw new IllegalStateException("Main thread not allowed to quit."); } synchronized (this) { if (mQuitting) { return; } mQuitting = true;//safe looper中传入判断是否安全退出//安全退出则只移除等待传递的消息否则清空所有 if (safe) { removeAllFutureMessagesLocked(); } else { removeAllMessagesLocked(); } // We can assume mPtr != 0 because mQuitting was previously false. nativeWake(mPtr); } }
Looper运作
核心部分
public static void loop() { //拿到Looper对象 final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); }//拿到消息队列 final MessageQueue queue = me.mQueue;//重置并获取当前线程跟踪令牌 确保线程身份不变 Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity();//looper维持的无限循环 for (;;) {// 消息出队 获取消息 Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } // This must be in a local variable, in case a UI event sets the logger final Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } final long traceTag = me.mTraceTag; if (traceTag != 0 && Trace.isTagEnabled(traceTag)) { Trace.traceBegin(traceTag, msg.target.getTraceName(msg)); }//拿到消息后进行消息分发 try { msg.target.dispatchMessage(msg); } finally { if (traceTag != 0) { Trace.traceEnd(traceTag); } } if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); }//事件分发后判断线程身分是否有变 final long newIdent = Binder.clearCallingIdentity(); if (ident != newIdent) { Log.wtf(TAG, "Thread identity changed from 0x" + Long.toHexString(ident) + " to 0x" + Long.toHexString(newIdent) + " while dispatching to " + msg.target.getClass().getName() + " " + msg.callback + " what=" + msg.what); }//消息处理完成后标记为已使用 扔回回收池中 并清空消息的属性变量等信息 msg.recycleUnchecked(); } }
消息如何出队 下一篇会说下MessageQueue和message
阅读全文
0 0
- Looper源码细说
- Android源码解析--Looper
- Looper源码解析
- Looper源码分析
- Looper、Handler源码分析
- Android源码解析--Looper
- Android Looper 源码笔记
- android Looper源码分析
- Android Looper源码解析
- android Looper 源码解析
- Handler Looper Message源码研究
- Handler Looper Message源码研究
- Handler与Looper源码分析
- Handler,message,Looper源码解析
- [Android源码]分析之Looper
- android Handler & Looper 源码解读
- Handler-Looper-Message源码分析
- Handler Looper MessageQueue源码解析
- React Native安卓微信分享集成
- linux下查看文件编码及修改编码
- Hadoop完全伪分布式搭建
- Android 系统 Settings 启动流程详解
- SpringSecurity学习【命名空间初体验】
- Looper源码细说
- 责任链模式
- 【Spring】Spring Framework Reference Documentation中文版37
- 【未写完】windows64位 php安装ZBarCodeImage二维码识别
- 项目小总结
- Kinect虚拟试衣间开发(5)-动作识别
- Uiautomator2.0+junit4
- Fiddler工具使用教程
- ClamAV工作