文章目录 一、Looper 初始化 二、Looper 遍历消息队列 MessageQueue 三、完整 Looper 代码 一、Looper 初始化 ---- Looper 是 线程本地变量 , 在每个线程中..., 就创建一个 Looper sThreadLocal.set(new Looper()); } 二、Looper 遍历消息队列 MessageQueue ---- 在 Looper...Looper looper = Looper.looper(); // 从当前线程的 Looper 获取 消息队列 MessageQueue MessageQueue...Looper * @return */ public static Looper looper(){ return sThreadLocal.get();...Looper looper = Looper.looper(); // 从当前线程的 Looper 获取 消息队列 MessageQueue MessageQueue
Handler、Looper、MessageQueue基本了解可以看下这篇文章 Android源码解读-Handler、Loop、MessageQueue 一、MessageQueue如何实现Message...二、Looper.loop是一个死循环,拿不到需要处理的Message就会阻塞,那在UI线程中为什么不会导致ANR?...如果当前Looper不阻塞,执行完成,那app直接嗝屁。 2.阻塞后为什么还能跳转页面等操作 这个问题是2个问题。第一个是如何执行页面跳转等操作,第二个是阻塞后为什么还能操作页面。...我们可以看到ActivityThread定义了内部类Handler,他和Looper都是在同一线程即主线程。...Handler可以接受来自binder线程的数据,比如收到msg=H.LAUNCH_ACTIVITY,添加到MessageQueue中,Looper监测有数据了,通过Handler,把消息发出去,最终则调用
文章目录 一、什么是handler 二、handler消息机制原理 三、Handler消息机制组件 Handler Message Looper MessageQueue 三、Handler的三种使用方式...生产者Handler在异步线程通过sendMessageDelayed() 将消息添加至MessageQueue, 消费者Looper通过loop()中死循环将MessageQueue中的msg取出后发送给产生此...Handler消息机制组件 Handler public Handler(Callback callback, boolean async) { //mLooper每个线程只有唯一一个Looper...( "Can't create handler inside thread that has not called Looper.prepare()");...; if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't
theme: fancy 数量关系 Looper.prepare()将Looper存储到ThreadLocal中,保证一个线程只有一个Looper,MessageQuene又是在Looper的构造方法中进行的初始化...所以一个线程一个Looper一个MessageQuene多个Handler 主线程和子线程使用区别 主线程为什么不用进行Looper.prepare()和Looper.loop()方法的调用就可以使用Hnadler...app入口类ActivityThread的main()中就已经调用了Looper.prepareMainLooper()和Looper.loop()两个方法。...所以主线程也要调用只不过ActivityThread帮你做了 大概流程 Looper中for(;;)死循环调用MessageQuene的next()方法(该方法也为for(;;)死循环)取出最新消息。...其实只是Java层的Mq没有消息,Native里面也有Mq和Looper,例如接收底层点击事件通过单独的一个InputQuene队列,Native层的消息处理是比Java的优先级高的,所以Java发送Message
(主线程除外,主线程系统会自动为其创建Looper对象,开启消息循环) Looper对象通过MessageQueue来存放消息和事件。...一个线程只能有一个Looper,对应一个MessageQueue。 通常是通过Handler对象来与Looper交互的。...Handler可看做是Looper的一个接口,用来向指定的Looper发送消息及定义处理方法。 常用的方法: 方法 含义 Looper.myLooper() 获取当前进程的looper对象。...Looper.getMainLooper() 用于获取主线程的Looper对象。...() 原因是因为非主线程中默认没有创建Looper对象,需要先调用Looper.prepare()启用Looper。
理解 一个Thread只有一个 Looper, 每个Looper都有它对应的MessageQueue。 多个Handler可以向MessageQueue发送Message或Runnable。...Looper依次处理MessageQueue中的Message(或Runnable),将Message发送给相应的Handler处理。...Looper https://developer.android.com/reference/android/os/Looper.html 理解用的关系图 该教程 中的 http://www.runoob.com...msg) { // process incoming messages here } }; Looper.loop...return queue.enqueueMessage(msg, uptimeMillis); } 通过设置msg的target为handler对象自己, 来标记这个Message 然后看Looper
} return queue.enqueueMessage(msg, uptimeMillis); } 通过dispatchMessage()来调用具体的处理,由Looper.loop...(needWake) { nativeWake(mPtr); } } return true; } 之后Looper...最后再来说下Looper,Looper是一个循环处理器,负责消息的分发处理。...通过Looper.loop()不停的处理MessageQueue中的消息,直到消息队列为空,之前已经提到Loop通过queue.next()方法从MessageQueue 中获取等待处理的消息 /**...me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare
Handler和Looper Handler我们都知道,它需要和Looper绑定,当Handler在主线程创建,则会默认绑定主线程的Looper,当是在子线程创建,则需要在Handler的构造方法里传入子线程的...Looper的对象。...其实到这里只是知道如何用Handler和Looper来实现线程通信,想知道真正的原理,还需要看Looper的源码。...final ThreadLocal sThreadLocal = new ThreadLocal(); 每当我们用 Looper.myLooper()获取当前线程的Looper...Looper的原理可以总结如下, · 每个线程都可以创建一个Looper,它会保存在当前线程对应的ThreadLocal里 · Handler需要绑定对应线程的Looper对象 · 线程在创建完Looper
每个应用在启动的时候会自动创建一个Looper,每个线程只能有一个Looper,因为这个是一个线程私有变量。下面是Looper成员的关系图。...类图 可以发现Fwk和Native都有一套Looper,而包含关系正好相反,Fwk层是Looper包含MessageQueue,而Native是MessageQueue包含Looper,Fwk的具体实现是完全由...这儿调用了Looper.prepareMainLooper(),这个就是为主线程生成默认的Looper,如果普通线程需要使用Handler就需要自己手动创建Looper了。...对于普通线程,Looper就可以是允许退出的了,这块可以通过prepare的参数来控制。那如何拿到主线程Looper呢?...void Looper::setForThread(const sp& looper) { sp old = getForThread(); // also has
Looper.loop(); ...... } public boolean quit() { Looper looper = getLooper();...在线程的run方法中调用Looper的prepare()方法进行准备工作,准备之后就可以通过Looper.myLooper获取到当前的线程的Looper了。...接下来分析Looper的实现。 而且可以quit来退出线程,quit方法中获取当前线程的looper,不为null会调用looper对象quit方法退出。...如果从sThreadLocal获取Looper对象不为null,说明线程已经绑定了Looper,直接抛出异常。...主线程中的Looper 主线程中的消息的管理也是通过Looper来实现的。它与普通线程的Looper不同的是有特殊的方法,但原理基本一致。
Looper.loop(); ...... } 这个就是系统UI线程的一个Looper 1.创建Looper prepareMainLooper方法只能调用一次 public static void...sThreadLocal.set(new Looper(quitAllowed)); } 1.这个会判断当前线程ThreadLocal是否已经存在Looper,如果不存在,则创建一个新Looper存放在...2.我们可以看出,一个线程只能有一个Looper,多次调用prepareMainLooper会报错 我们来看看Looper创建实例 private Looper(boolean quitAllowed)...(); } 上面我们知道Looper的来源,创建Looper的时候同时创建了MessageQueue。...接下来看下,Looper是如何无限循环遍历消息队列的。
我们常说子线程使用Handler之前,需要先进行Looper.prepare();而主线程不需要额外添加代码,为什么主线程不需要手动操作Looper呢?它又是在哪里做prepare操作的呢?...main方法里会调用Looper.prepareMainLooper(); 下面是通过Looper.prepareMainLooper();跟进去的源码。.../** * Initialize the current thread as a looper, marking it as an * application's main looper...static final ThreadLocal sThreadLocal = new ThreadLocal(); /** * Return...();与Looper.prepare();有什么区别?
前言 我做了两期有关Looper的视频,目前来看播放量还不错,有兴趣的可以去B站观看,视频中我提到Looper采用pipe机制wake,纠正一下自己的错误,新版本的Looper已经采用eventfd代替...王小二图解Android【001】Looper上篇 王小二图解Android【002】Looper下篇 ?...一、Android 5.1或更早版本 //初始化 Looper::Looper(bool allowNonCallbacks) : mAllowNonCallbacks(allowNonCallbacks...mWakeReadPipeFd result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem); } void Looper...二、Android 6.0或更高的版本 Looper::Looper(bool allowNonCallbacks) : mAllowNonCallbacks(allowNonCallbacks
Handler的运行还依赖MessageQueue、Looper,及Looper内部使用到的ThreadLocal。...Looper会在消息队列中无限循环的查找消息,有消息就取出,没有就等待。 ThreadLocal本质作用是在每个线程中存储数据。在Looper中的作用就是给每个线程存Looper实例。...因为我们知道,创建Handler时是需要线程的Looper实例的,而非UI线程默认是没有Looper的。...looper....//主线程looper开启 Looper.loop(); //因为主线程的Looper是不能退出的,退出就无法接受事件了。
调用多次 Looper.prepare() 并不会关联多个 Looper,还会抛出异常,那能不能直接 new 一个 Looper 关联上呢?...所以从 Looper 源码里掌握的信息来看,想给一个线程关联多个 Looper 的路不通。...Looper 对象。...构造 Handler 对象的时候如果不传 Looper 参数,会默认使用当前线程关联的 Looper,如果当前线程没有关联 Looper,会抛出异常。...Handler 与 Looper 是多对一的关系,创建 Handler 实例时要么提供一个 Looper 实例,要么当前线程有关联的 Looper。
Looper运行模型.jpg APP端UI线程都是Looper线程,每个Looper线程中维护一个消息队列,其他线程比如Binder线程或者自定义线程,都能通过Handler对象向Handler所依附消息队列线程发送消息...Looper对象,Looper.prepare只能调用一次,再次调用会抛出异常。...其实prepare的作用就是新建一个Looper对象,而在new Looper对象的时候,会创建关键的消息队列对象: private Looper(boolean quitAllowed) {...RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); }...Looper Java层与native层关系7.0.jpg 在更早的Android版本中,同步逻辑是利用管道通信实现的,不过思想是一致的,看一下4.3的代码 Looper::Looper(bool allowNonCallbacks
而MessageQueue是由Looper负责管理的,也就是说,如果希望Handler正常工作的话,就必须在当前线程中有一个Looper对象。那么又该如何保障当前线程中一定有Looper对象呢?...(new Looper(quitAllowed)); } 在创建Looper对象前先会去判断ThreadLocal中是否已经存在Looper对象,如果不存在就新创建一个Looper对象并且存放ThreadLocal...()方法内部源码我们可以知道,首先会通过myLoooper()去获取一个Looper对象,如果Looper对象为null,就会报出一个我们非常熟悉的错误提示,“No Looper;Looper.prepare...mainHandler = new Handler() 等价于 new Handler(Looper.myLooper())Looper.myLooper():获取当前进程的looper对象, Looper.getMainLooper...() 原因是非主线程中默认没有创建Looper对象,需要先调用Looper.prepare()启用Looper,然后再调用Looper.loop()。
四组件对应关系 : Handler 机制中的上述四者的对应关系 : 一个线程中只能有一个 Looper 及 Looper 中封装的 MessageQueue , 每个 Looper 可以为多个 Handler...Looper 内部 , 每个 Looper 中只定义了一个 MessageQueue ( 消息队列 ) , 因此每个线程也只能有一个 MessageQueue ; 线程 与 Looper ( 消息遍历者...() 方法 , 将线程转为 Looper 线程 , 因为 创建 Handler 时 , 会关联线程的 Looper 对象 , 普通的子线程是没有 Looper 对象的 , 调用 Looper.prepare...Looper 线程 : 如果要将 Handler , Looper 机制引入到线程中 , 使某线程具有接收 Message ( 消息 ) , 执行某项操作的功能 , 需要将该线程转为 Looper 线程...将线程转为 Looper 线程 //主要是创建 Looper 放入 ThreadLocal 对象中 Looper.prepare(); //3.
Handler持有 Looper 的实例,直接持有looper的消息队列。 属性与构造器 Handler类中持有的实例,持有looper,messageQueue等等。...,并负责处理Looper分给它的消息 2.MessageQueue:管理Message,由Looper管理 3.Looper:每个线程只有一个Looper,比如UI线程中,系统会默认的初始化一个Looper...获取当前线程的MessageQueue方法是Looper.myQueue()。通过Looper.getMainLooper()获取到主线程的looper。...(); // Looper开始运行 } } 调用了Looper.loop()之后,looper开始运行。...Looper 方法 准备方法,将当前线程初始化为Looper。
每个线程Thread都会维护一个threadLocals变量:ThreadLocalMap。这个类是ThreadLocal的静态内部类。当进行ThreadLoc...
领取专属 10元无门槛券
手把手带您无忧上云