Handler创建,必须有个一个Looper,主线程自己创建了。其他线程需要自己创建,默认是没有的。创建方法

  1. 这种方法是先创建一个系统定义好的HandlerThread,这个是跑在非UI线程中的,已经创建好了looper,直接用就可以了.创建handler有多个构造函数,具体看源码

    HandlerThread threadhandler = new HandlerThread("1111");
    threadhandler.start();
    myhandler = new myHandler(threadhandler.getLooper());

   2. 自己创建一个新的线程,在线程中调用Looper.prepare();然后写处理message回调方法,接着还要调用looper.loop();
  class LooperThread extends Thread {        public Handler mHandler;         public void run() {          Looper.prepare();

          mHandler = new Handler() {              public void handleMessage(Message msg) {                  // process incoming messages here             }         };

          Looper.loop();     }  }
  为什么一定要有一个Looper呢?  因为handler的无参数构造函数里需要looper,如果为空就抛异常。  如何设置looper?   调用Looper.prepare();这里会判断当前的线程是不是已经有looper了,有的话会抛异常,这就是说一个线程只能有一个looper。   Message是什么,有什么用?   存放消息的用的,它有很多属性。特别说明target,表示的就是处理它的handler,next属性,这就是利用了链表结构来构造的消息队列,message.next表示着当前消息的下一个,是按照时间来的,只能顺序不能反过来,他没有prev属性。   这里需要说一下他的Spool静态属性,这是一个消息池,Spool自己就是一个Message对象,刚开始的时候他是null的,什么时候它有东西的呢?
  void recycleUnchecked() {      // Mark the message as in use while it remains in the recycled object pool.      // Clear out all other details.      flags = FLAG_IN_USE;      what = 0;      arg1 = 0;      arg2 = 0;      obj = null;     replyTo = null;      sendingUid = -1;      when = 0;      target = null;      callback = null;      data = null;

      synchronized (sPoolSync) {          if (sPoolSize < MAX_POOL_SIZE) {              next = sPool;              sPool = this;              sPoolSize++;          }      }  }  看这个方法,这个方法是looper中循环处理完一个message之后做的事情,它回收了这个message,并且将这个被回收的message和已有的Spool链接起来,再将Spool指向这个回收的message,利用这种方法将回收的message都给串了起来。  message -> spool -> null  spool(被回收的message)-> message(旧的spool) -> null  消息池怎么被使用的?  public static Message obtain() {
    synchronized (sPoolSync) {        if (sPool != null) {            Message m = sPool;            sPool = m.next;            m.next = null;            m.flags = 0; // clear in-use flag            sPoolSize--;            return m;        }    }      return new Message();  }
  利用obtain的方法得到一个消息池中的第一个空message,并且spool指向第二个元素,剩余的空消息数-1;

   MessageQueue是什么,有什么用?   用来操作messages,例如handler发送消息过来,他需要把消息按照顺序串起来。还有处理完消息后他需要把消息从消息队列中删除等等。   handler有什么用?   发送和处理消息。handler通过sendmessage等方法发送消息,最终都是通过sendMessageAtTime(这里最终是调用了enqueueMessage方法,其中uptimeMillis参数是SystemClock.uptimeMillis() + delayMillis,所以想要优先处理runable,就是要让时间戳在所有message之前,利用
sendMessageAtFrontOfQueue方法,这个参数会传递0,这样就会优先处理了)来处理发送给MessageQueue。然后通过looper回调函数msg.target.dispatchMessage(msg)-->handler的handleMessage()方法具体处理。
   handler还可以使用post方法将runnable传给消息队列message有callback属性,在looper的dispatchMessage()方法中,如果是runnable就直接run()了;

 最后有个疑问:到底是什么样的机制可以让looper循环去处理message?

   while (true) {

          Message msg = queue.next(); // might block    

    if (msg != null) {

    if (msg.target == null) {    

      return;

}

    if (me.mLogging!= null) me.mLogging.println(  ">>>>> Dispatching to " + msg.target + " "

     + msg.callback + ": " + msg.what   );

    msg.target.dispatchMessage(msg);

    if (me.mLogging!= null) me.mLogging.println(  "<<<<< Finished to    " + msg.target + " "

     + msg.callback);

      msg.recycle();

    }

  看到Message msg = queue.next(); // might block 这句话,获得待处理的message,这里可能会堵塞,没有message的时候就循环等待,直到messageQueue退出    现在再看看queue.next方法
  if (msg != null && msg.target == null) {      // Stalled by a barrier.  Find the next asynchronous message in the queue.      do {          prevMsg = msg;          msg = msg.next;      } while (msg != null && !msg.isAsynchronous());  }
  这部分代码进入条件是target是null,那么什么时候target会是null呢,首先我们要明确,我们只有2种方法往messageQueue的mMessages里插入message---enqueueMessage(sendMessage等最终都是走的它)和enqueueBarrier。我们用handler在setMessage的时候enqueueMessage方法已经
  msg.target = this;  而且如果我们使用的是带参数的Message中的obtain方法也会设置target。  那么无疑就是enqueueBarrier方法,这个方法只有一个入口,就是Looper的postSyncBarrier(),它会返回一个int值,用于之后的removeSyncBarrier(int)。
  int enqueueSyncBarrier(long when) {      // Enqueue a new sync barrier token.      // We don't need to wake the queue because the purpose of a barrier is to stall it.     synchronized (this) {        final int token = mNextBarrierToken++;        final Message msg = Message.obtain();//这里返回一个target为null的Message        msg.markInUse();        msg.when = when;        msg.arg1 = token;    .....    }  }  然后接着看queue.next,如果是阻断msg,那么就一直找到msg是isAsynchronous的,然后接着处理,这个isAsynchronous有2种设置方法,一个是handler构造参数里面传的,那么所有的sendMessage都会打上异步标签。还有一种就是单独调用一个message的setAsynchronous。  这样的话,当阻断的时候就会跳过普通的message,找到异步message去执行。  接着往下看next();
  // Got a message.  mBlocked = false;  if (prevMsg != null) {      prevMsg.next = msg.next;//如果阻断的话,这里prevMsg就不是空,那么就会直接把标签是异步的message的上一个message的next直接指向标签是异步的message的下一个message,其实就是把异步message从消息队列中给抽出去了
  } else {      mMessages = msg.next;//这里就是普通message的处理步骤,消息队列少了第一个元素  }  msg.next = null;  if (false) Log.v("MessageQueue", "Returning message: " + msg);  return msg;  到这里,阻断message还是在消息队列中,下次循环还是依照这个顺序执行。除非我们手动调用removeSyncBarrier方法才能正常处理普通的message。
  这里得到个结论,mMessages的第一个元素不一定就是本次待处理的message。
 这个阻断在源码中有地方使用:scheduleTraversals这个方法,这个方法是view的measure,layout,draw三部曲的入口。
void scheduleTraversals() {    if (!mTraversalScheduled) {        mTraversalScheduled = true;        mTraversalBarrier = mHandler.getLooper().postSyncBarrier();//这里,使用了阻断,此时只有message是异步的才可以被执行。        mChoreographer.postCallback(                Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);        if (!mUnbufferedInputDispatch) {            scheduleConsumeBatchedInput();        }        notifyRendererOfFramePending();    }}
mTraversalRunnable这个Runnable执行的代码是
void doTraversal() {    if (mTraversalScheduled) {        mTraversalScheduled = false;        mHandler.getLooper().removeSyncBarrier(mTraversalBarrier);//已经开始执行了,就把阻断remove掉,view展示完毕后继续正常处理普通的message

        if (mProfile) {     ....     }      }  }优点快速展示,想了半天,为啥他不使用sendMessageAtFrontOfQueue这个方法优先执行mTraversalRunnable呢?可能原因,我们也可以主动调用改方法,那么岂不是就有可能我们的runnable优先与系统展示view了?使用阻断,他内部还是按照时间戳顺序执行的,就保证了view展示优先执行~!!!!!

  接着看next();  
// Run the idle handlers.// We only ever reach this code block during the first iteration.for (int i = 0; i < pendingIdleHandlerCount; i++) {    final IdleHandler idler = mPendingIdleHandlers[i];    mPendingIdleHandlers[i] = null; // release the reference to the handler

    boolean keep = false;    try {        keep = idler.queueIdle();    } catch (Throwable t) {        Log.wtf("MessageQueue", "IdleHandler threw exception", t);    }

    if (!keep) {        synchronized (this) {            mIdleHandlers.remove(idler);        }    }}
这里还有代码,这是干嘛的?这这个就是执行idle handlers的,当之前的message,一个都找不到的时候,说明空闲,这个时候就可以执行IdleHandler了使用方法就是调用MessageQueue的addIdleHandler方法。

转载于:https://www.cnblogs.com/liming-saki/p/4515283.html

android-handler、looper、messageQueue、message相关推荐

  1. Android中的Handler、Looper和MessageQueue的使用以及原理

    提到Handler大家一定都不陌生,通常我们都是在子线程通过在主线程中创建的Handler对象切换到主线程中去更新View的显示内容,然而很少接触Looper更没有感觉到MessageQueue的存在 ...

  2. Handler、Looper与MessageQueue源码分析

    在Android中可以通过Handler来更新主线程中UI的变化,更新UI只能在主线程中进行更新,而为了让其他线程也能控制UI的变化,Android提供了一种机制Handler.Looper与Mess ...

  3. Android Handler与Looper原理简析

    一直感觉自己简直就是一个弱智,最近越来越感觉是这样了,真的希望自己有一天能够认同自己,认同自己. 本文转载于:https://juejin.im/post/59083d7fda2f60005d14ef ...

  4. Handler与looper、MessageQueue的关系

    Handler与Looper.MessageQueue的关系 1. Handler机制? 只要遵循Android使用handler来更新UI的机制,我们就不用关心多线程的问题,所有的更新UI的操作都是 ...

  5. android handler的机制和原理_一文搞懂handler:彻底明白Android消息机制的原理及源码

    提起Android消息机制,想必都不陌生.其中包含三个部分:Handler,MessageQueue以及Looper,三者共同协作,完成消息机制的运行.本篇文章将由浅入深解析Android消息机制的运 ...

  6. Android Handler的原理

    简介 在 Android 中,只有主线程才能操作 UI,但是主线程不能进行耗时操作,否则会阻塞线程,产生 ANR 异常,所以常常把耗时操作放到其它子线程进行.如果在子线程中需要更新 UI,一般是通过 ...

  7. Android进阶知识树——Android Handler消息机制

    1.概述 在安卓程序启动时,会默认在主线程中 运行程序,那如果执行一些耗时的操作则UI就会处于阻塞状态,出现界面卡顿的现象,再者用户的多种操作,系统是如何做到一一处理的,系统又是如何管理这些任务的,答 ...

  8. Android Handler杂记(结合别人的blog)

    handler泄露问题: http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1123/2047.html http://blog.c ...

  9. Android多线程源码学习笔记一:handler、looper、message、messageQueue

    最近在学习Android多线程相关知识的源码,现在把自己的笔记整理一下,写出来加深印象. Android多线程通讯的核心是handler.looper.message.messageQueue,这篇文 ...

  10. android handler、looper、message、messageQueue、

    一:handler,looper,message,messagequeue,thread handler: 消息处理着,负责Message消息的发送(handler.sendMessage(....) ...

最新文章

  1. vfprintf php,PHP vfprintf() 函数
  2. STM32系列--初识寄存器1
  3. 【软考-软件设计师】校验码
  4. OpenGL基本窗口和OpenGL 初始化
  5. “==”和equals()那些事
  6. c++ socket线程池原理_ThreadPoolExecutor线程池实现原理+源码解析
  7. 让经纬度数据带矢量方向_惊艳!这样处理可得到细至可用于交通模型的路网数据...
  8. 【技术人快报】美军计划换用Linux系统+安卓系统“克隆漏洞”曝光
  9. 回溯算法背包问题迭代c语言,回溯法解决0_1背包问题(迭代和递归)
  10. 诺基亚N9手机升级后PR1.3后反应迟钝、发热、耗电快的问题
  11. 照片宽高比怎么设置_2019年中级会计报名照片上传完整攻略
  12. Gauss光束在空间中的分布
  13. Vue学习--黑马电商管理系统
  14. c语言数组及其下标引用,C语言之数组下标引用与间接引用
  15. 《数据结构》第五章 树和二叉树 同学问题收集站
  16. ttk progress bar的显示
  17. Android 360开源全面插件化框架RePlugin 实战
  18. 双排桩弯矩Matlab求解程序,考虑开挖过程椅式双排桩内力及变形分析
  19. 《东周列国志》第五十一回 责赵盾董狐直笔 诛斗椒绝缨大会
  20. 2019年计算机二级获证条件,2019年下半年全国计算机等级考试报考简章

热门文章

  1. POJ1679 The Unique MST —— 次小生成树
  2. ES6 变量解构赋值
  3. [bzoj1969] [Ahoi2005]LANE 航线规划
  4. 网络安全以及常见的网络攻击
  5. Hadoop之倒排索引
  6. Node.js入门初体验
  7. label字符自动换行(转自网络)
  8. 【Oracle】 expdp/impdp
  9. Mootools:Hash中的null值
  10. WINX的消息分派机制(续)