• 网上看了10篇左右的博客,都没有把为什么要用handler.post方法说清楚,云里雾里的。

  • 本文我想说明的是为什么要使用handler.post方法,它和常用的handler.sendmessage方法的区别是什么?

首先,写这篇博客希望大家多多交流与指正,鄙人也不敢保证内容完全正确。

  • 其实写的时候我犹豫了要不要把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方法还有迷惑的同学能有所收获,最后希望大家多多交流

首先,postpostDelay都是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