建设银行河南省分行招聘网站,网站建设包含哪些费用,仿织梦长沙网站公司,网站制作哪些公司好前几天#xff0c;和同事探讨了一下Android中的消息机制#xff0c;探究了消息的发送和接收过程以及与线程之间的关系。虽然我们经常使用这些基础的东西#xff0c;但对于其内部原理的了解#xff0c;能使我们更加容易、合理地架构系统#xff0c;并避免一些低级错误。 对… 前几天和同事探讨了一下Android中的消息机制探究了消息的发送和接收过程以及与线程之间的关系。虽然我们经常使用这些基础的东西但对于其内部原理的了解能使我们更加容易、合理地架构系统并避免一些低级错误。 对于这部分的内容将分成4小节来描述 1.职责与关系 2.消息循环 3.线程与更新 4.几点小结 -------------------------------------------------------------------------------------------------- 1 接下来我们开始这部分的内容首先了解一下各自的职责及相互之间的关系。 职责 Message消息其中包含了消息ID消息处理对象以及处理的数据等由MessageQueue统一列队终由Handler处理。 Handler处理者负责Message的发送及处理。使用Handler时需要实现handleMessage(Message msg)方法来对特定的Message进行处理例如更新UI等。 MessageQueue消息队列用来存放Handler发送过来的消息并按照FIFO规则执行。当然存放Message并非实际意义的保存而是将Message以链表的方式串联起来的等待Looper的抽取。 Looper消息泵不断地从MessageQueue中抽取Message执行。因此一个MessageQueue需要一个Looper。 Thread线程负责调度整个消息循环即消息循环的执行场所。 关系 HandlerLooper和MessageQueue就是简单的三角关系。Looper和MessageQueue一一对应创建一个 Looper的同时会创建一个MessageQueue。而Handler与它们的关系只是简单的聚集关系即Handler里会引用当前线程里的特定Looper和MessageQueue。 这样说来多个Handler都可以共享同一Looper和MessageQueue了。当然这些Handler也就运行在同一个线程里。 2 接下来我们简单地看一下消息的循环过程 生成 Message msg mHandler.obtainMessage(); msg.what what; msg.sendToTarget(); 发送 MessageQueue queue mQueue; if (queue ! null) { msg.target this; sent queue.enqueueMessage(msg, uptimeMillis); } 在Handler.java 的sendMessageAtTime(Message msg, long uptimeMillis)方法中我们看到它找到它所引用的MessageQueue然后将Message的target设定成自己目的是为了在处理消息环节Message能找到正确的Handler再将这个Message纳入到消息队列中。 抽取 Looper me myLooper(); MessageQueue queue me.mQueue; while (true) { Message msg queue.next(); // might block if (msg ! null) { if (msg.target null) { // No target is a magic identifier for the quit message. return; } msg.target.dispatchMessage(msg); msg.recycle(); } } 在Looper.java 的loop()函数里我们看到这里有一个死循环不断地从MessageQueue中获取下一个next方法Message然后通过Message中携带的target信息交由正确的Handler处理dispatchMessage方法。 处理 if (msg.callback ! null) { handleCallback(msg); } else { if (mCallback ! null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } 在Handler.java的dispatchMessage(Message msg)方法里其中的一个分支就是调用handleMessage方法来处理这条Message而这也正是我们在职责处描述使用Handler时需要实现handleMessage(Message msg)的原因。 至于dispatchMessage方法中的另外一个分支我将会在后面的内容中说明。 至此我们看到一个Message经由Handler的发送MessageQueue的入队Looper的抽取又再一次地回到Handler的怀抱。而绕的这一圈也正好帮助我们将同步操作变成了异步操作。 3剩下的部分我们将讨论一下Handler所处的线程及更新UI的方式。 在主线程UI线程里如果创建Handler时不传入Looper对象那么将直接使用主线程UI线程的Looper对象系统已经帮我们创建了在其它线程里如果创建Handler时不传入Looper对象那么这个Handler将不能接收处理消息。在这种情况下通用的作法是 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(); } } 在创建Handler之前为该线程准备好一个LooperLooper.prepare然后让这个Looper跑起来Looper.loop抽取Message这样Handler才能正常工作。 因此Handler处理消息总是在创建Handler的线程里运行。而我们的消息处理中不乏更新UI的操作不正确的线程直接更新UI将引发异常。因此需要时刻关心Handler在哪个线程里创建的。 如何更新UI才能不出异常呢SDK告诉我们有以下4种方式可以从其它线程访问UI线程 · Activity.runOnUiThread(Runnable) · View.post(Runnable) · View.postDelayed(Runnable, long) · Handler 其中重点说一下的是View.post(Runnable)方法。在post(Runnable action)方法里View获得当前线程即UI线程的Handler然后将action对象post到Handler里。在Handler里它将传递过来的action对象包装成一个MessageMessage的callback为action然后将其投入UI线程的消息循环中。在 Handler再次处理该Message时有一条分支未解释的那条就是为它所设直接调用runnable的run方法。而此时已经路由到UI线程里因此我们可以毫无顾虑的来更新UI。 4 几点小结 · Handler的处理过程运行在创建Handler的线程里 · 一个Looper对应一个MessageQueue · 一个线程对应一个Looper · 一个Looper可以对应多个Handler · 不确定当前线程时更新UI时尽量调用post方法 转自http://www.open-open.com/lib/view/open1327558863765.html 转载于:https://www.cnblogs.com/Mr-Hannibal/archive/2012/02/04/2337845.html