首先,写这篇博客希望大家多多交流与指正,鄙人也不敢保证内容完全正确。
-
其实写的时候我犹豫了要不要把handler和post的源码搬出来说,会显得更有说服力,但是我看的那些博客都是附带源码说明问题的,结果长篇大论,却还说了个云里雾里,所以我不做搬运工,讲明道理,让大家知道是怎么一回事,然后感兴趣的去自己去看源码,OK。
1 先看用法1之主线程中使用:
new Handler().post(new Runnable() {
@Override
public void run() {
mTest.setText("post");//更新UI
可以看到,new了Runnable像是开启了一个子线程,但是不然,大家可以看到这儿调用的是run方法,而不是start方法,因此并不是子线程,其实还是在主线程中,那为什么又要使用post方法呢?其实一般不这样用,也没人这样用,并没有多大意义,这就像是在主线程中给主线程sendmessage,并没有什么意义(我们知道sendmessage是子线程为了通知主线程更新UI的),主线程是可以直接更新UI的。
2 再看用法2之子线程中使用:
Handler handler;
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
handler.post(new Runnable() {
@Override
public void run() {
mTest.setText("post");//更新UI
} catch (InterruptedException e) {
e.printStackTrace();
}).start();
由上面总结我们知道这儿的post并不是新开启的子线程,存在的子线程只有一个,即为new的Thread,那么为什么我们在其中可以settext做更新UI的操作呢? 其实post方法post过去的是一段代码,相当于将这个Runable体放入消息队列中,那么looper拿取的即为这段代码去交给handler来处理,其实也相当于我们常用的下面这段代码:
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 0:
mTest.setText("handleMessage");//更新UI
break;
看起来熟悉吧,就是用这个Runnable体代替了上面这一大段代码,当然,我们的post方法就可以执行UI操作了。
平常情况下我们一个activity有好多个子线程,那么我们都会采用上面这种handleMessage(msg)方式,然后case 0:case 1:等等,但是当我们只有一个子线程时呢,用post反而比上面一大串代码轻便了不少,何乐而不为呢?
讲到这儿希望对post方法还有迷惑的同学能有所收获,最后希望大家多多交流
首先,post和postDelay都是Handler的方法,用以在子线程中发送Runnable对象的方法;
其次,Android中post()方法可以直接在非UI线程中更新UI,不同与Handelr的Send类方法,需要进行切换;
最后,两个方法在实现UI线程事件的时间上有所区别,postDelayed()方法用...
MessageQueue.next()方法中,进行消息遍历的时候,如果发现了一个msg.target =null的时候,就说明当前消息就是一个屏障消息,然后会遍历消息链表直到msg.isAsynchronous为true,也就是找到第一个异步消息的时候,才能继续进行消息的分发和处理,否则会一直遍历直到移除屏障消息,然后才能够执行队列中的同步消息。消息的处理顺序为3,4,1,2,同步屏障加入得到消息队列中后,会优先处理消息队列中的异步消息,直到移除屏障消息之后才会处理消息队列中的同步消息。
2. 延时任务
但是我一直有一个困惑,就是handler.post(r)这个方法有什么独特的作用?
通过看源码发现,post这个方法是把任务r转成一个message放进了handler所在的线程中的messageQueue消息队列中,并且是立刻发送的消息,这样它既不是异步的也不是延时的,所以问题来了:
1. 它和sendMessage()有什么区别?
2. 它有什么独特作用呢?
下结论之前我们先通过源码来分析:
* Causes the Runnable r to be
public final boolean postDelayed(Runnable r, long delayMillis){
return sendMessageDelayed(getPostMessage(r), delayMillis);
2. 我们再点进去看下 sendMessageDelayed()方法,
pub..
可以看到,绑定一个button,点击button后,在异步线程中模拟网络请求,当网络请求结束,改变button上的文字。结果:只有创建视图层次结构的原始线程才能接触其视图。说明除了主线程,其它线程不能更信UI.这个案例引出了两个个问题1.为什么在子线程不能更新UI?因为当多个子线程与主线程共同操作UI时,会出现操作不可控的现象。2.如果想要在子线程更新UI怎么办?这就需要用到我们的Handler了。
原帖链接:http://byandby.javaeye.com/blog/832467http://byandby.javaeye.com/blog/832915Handler的使用(一) Handler基本概念:
Handler主要用于异步消息的处理:当发出一个消息之后,首先进入一个消息队列,发送消息的函数即刻返回,而另外一个部分逐个的在消息队列中将消息取出,然后对消息进行出来,就是发送消息和接收消息不是同步的处理。
这种机制通常用来处理相对耗时比较长的操作。 使用一个例子简单的来介绍一下Hand
参考 “酱爆大头菜”:https://juejin.cn/post/6995854886386532388
本文就以生活点餐的例子再结合源码原理进行解析。希望对你有一点帮助。 来,咱们进入角色。
Handler,Looper,MessageQueue,Message的全程协作的关系就好比一个餐厅的整体运作关系
Handler好比点餐员
Looper好比后厨厨师长。
MessageQueue好比订单打单机。
Message好比一桌一桌的订单。
接下来我们回顾下我们餐厅点餐的场景,餐厅点餐分为标准点
这个 new Runnable() 依附于创建Handler的线程,
在绝对的UI线程中打印线程ID:System.out.println("UI Thread = " + Thread.currentThread().getId()); 下面在posdelayed中打印运行线程的
现在大部分人都很熟悉handler这个东西了,我们常用handler的场景无非有两个:1. 异步更新UI2. 延时任务但是我一直有一个困惑,就是handler.post(r)这个方法有什么独特的作用?通过看源码发现,post这个方法是把任务r转成一个message放进了handler所在的线程中的messageQueue消息队列中,并且是立刻发送的消息,这样它既不是异步的也不是延时的,所以问题来了...
在Android开发中,我们经常会遇到这样一种情况:在UI界面上进行某项操作后要执行一段很耗时的代码,比如我们在界面上点击了一个”下载“按钮,那么我们需要执行网络请求,这是一个耗时操作,因为不知道什么时候才能完成。为了保证不影响UI线程,所以我们会创建一个新的线程去执行我们的耗时的代码。当我们的耗时操作完成时,我们需要更新UI界面以告知用户操作完成了。所以我们可能会写出如下的代码:package ...
Handler 是一套消息处理机制,是Android SDK来处理异步消息的核心类
Handler有什么作用?
Handler 用于子线程与主线程通信。子线程可以通过Handler来通知主线程进行UI更新
Handler如何使用?
参考地址:Android之Handler用法总结
Android Developers 地址:http://www.android-doc.com/reference/android/os/Handler.html