Android消息机制(2)

在Android 中,线程内部或者线程之间进行信息交互时经常会使用消息,这些基础的东西如果我们熟悉其内部的原理,将会使我们容易、更好地架构系统,避免一些低级的错误。

下面我们分析下程序的运行过程:

1.onCreate()

首先启动服务时将会调用onCreate()方法,在该方法中我们new了一个HandlerThread对象,提供了线程的名字和优先级。

紧接着我们调用了start()方法,执行该方法将会调用HandlerThread对象的run()方法:

  1. public void run() {
  2. mTid = Process.myTid();
  3. Looper.prepare();
  4. synchronized (this) {
  5. mLooper = Looper.myLooper();
  6. notifyAll();
  7. }
  8. Process.setThreadPriority(mPriority);
  9. onLooperPrepared();
  10. Looper.loop();
  11. mTid = -1;
  12. }

在run()方法中,系统给线程添加的Looper,同时调用了Looper的loop()方法:

  1. public static final void loop() {
  2. Looper me = myLooper();
  3. MessageQueue queue = me.mQueue;
  4. while (true) {
  5. Message msg = queue.next(); // might block
  6. //if (!me.mRun) {
  7. //    break;
  8. //}
  9. if (msg != null) {
  10. if (msg.target == null) {
  11. // No target is a magic identifier for the quit message.
  12. return;
  13. }
  14. if (me.mLogging!= null) me.mLogging.println(
  15. ">>>>> Dispatching to " + msg.target + " "
  16. + msg.callback + ": " + msg.what
  17. );
  18. msg.target.dispatchMessage(msg);
  19. if (me.mLogging!= null) me.mLogging.println(
  20. "<<<<< Finished to    " + msg.target + " "
  21. + msg.callback);
  22. msg.recycle();
  23. }
  24. }
  25. }

通过源码我们可以看到loop()方法是个死循环,将会不停的从MessageQueue对象中获取Message对象,如果 MessageQueue 对象中不存在Message对象,则结束本次循环,然后继续循环;如果存在Message对象,则执行 msg.target.dispatchMessage(msg),但是这个msg的.target字段的值是什么呢?我们先暂时停止跟踪源码,返回到 onCreate()方法中。线程执行完start()方法后,我们可以获取线程的Looper对象,然后new一个ServiceHandler对象, 我们把Looper对象传到ServiceHandler构造函数中将使handler、looper和messageQueue三者建立联系。

2.onStartCommand()

执行完onStart()方法后,将执行onStartCommand()方法。首先我们从消息池中获取一个Message实例,然后给 Message对象的arg1、what、obj三个字段赋值。紧接着调用sendMessage(msg)方法,我们跟踪源代码,该方法将会调用 sendMessageDelayed(msg, 0)方法,而sendMessageDelayed()方法又会调用sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis)方法,在该方法中我们要注意该句代码msg.target = this,msg的target指向了this,而this就是ServiceHandler对象,因此msg的target字段指向了 ServiceHandler对象,同时该方法又调用MessageQueue 的enqueueMessage(msg, uptimeMillis)方法:

  1. final boolean enqueueMessage(Message msg, long when) {
  2. if (msg.when != 0) {
  3. throw new AndroidRuntimeException(msg
  4. + " This message is already in use.");
  5. }
  6. if (msg.target == null && !mQuitAllowed) {
  7. throw new RuntimeException("Main thread not allowed to quit");
  8. }
  9. synchronized (this) {
  10. if (mQuiting) {
  11. RuntimeException e = new RuntimeException(
  12. msg.target + " sending message to a Handler on a dead thread");
  13. Log.w("MessageQueue", e.getMessage(), e);
  14. return false;
  15. } else if (msg.target == null) {
  16. mQuiting = true;
  17. }
  18. msg.when = when;
  19. //Log.d("MessageQueue", "Enqueing: " + msg);
  20. Message p = mMessages;
  21. if (p == null || when == 0 || when < p.when) {
  22. msg.next = p;
  23. mMessages = msg;
  24. this.notify();
  25. } else {
  26. Message prev = null;
  27. while (p != null && p.when <= when) {
  28. pprev = p;
  29. pp = p.next;
  30. }
  31. msg.next = prev.next;
  32. prev.next = msg;
  33. this.notify();
  34. }
  35. }
  36. return true;
  37. }

该方法主要的任务就是把Message对象的添加到MessageQueue中(数据结构最基础的东西,自己画图理解下)。

handler.sendMessage()-->handler.sendMessageDelayed()-->handler.sendMessageAtTime()-->msg.target = this;queue.enqueueMessage==>把msg添加到消息队列中

3.handleMessage(msg)

onStartCommand()执行完毕后我们的Service中的方法就执行完毕了,那么handleMessage()是怎么调用的呢?在前 面分析的loop()方法中,我们当时不知道msg的target字段代码什么,通过上面分析现在我们知道它代表ServiceHandler对 象,msg.target.dispatchMessage(msg);则表示执行ServiceHandler对象中的 dispatchMessage()方法

  1. public void dispatchMessage(Message msg) {
  2. if (msg.callback != null) {
  3. handleCallback(msg);
  4. } else {
  5. if (mCallback != null) {
  6. if (mCallback.handleMessage(msg)) {
  7. return;
  8. }
  9. }
  10. handleMessage(msg);
  11. }
  12. }

该方法首先判断callback是否为空,我们跟踪的过程中未见给其赋值,因此callback字段为空,所以最终将会执行handleMessage()方法,也就是我们ServiceHandler类中复写的方法。在该方法将根据what字段的值判断执行哪段代码。

至此,我们看到,一个Message经由Handler的发送,MessageQueue的入队,Looper的抽取,又再一次地回到Handler的怀抱中。而绕的这一圈,也正好帮助我们将同步操作变成了异步操作。

时间: 2024-08-27 00:38:43

Android消息机制(2)的相关文章

【转】Android 消息机制

Android 消息机制 本文首先从整体架构分析了Android整个线程间消息传递机制,然后从源码角度介绍了各个组件的作用和完成的任务.文中并未对基础概念进行介绍,关于threadLacal和垃圾回收等等机制请自行研究. 基础架构 首先,我们需要从整体架构上了解一下Android线程通信都做了哪些工作.我们都知道,进程是操作系统分配资源的最小单位,一个进程中可以启动多个线程来执行任务,这些线程可以共享进程的资源但不分配资源,这里讲的资源主要是只内存资源.Android的线程间消息传递机制其实和我

Android消息机制字典型探

Android消息机制字典型探究(一) Android消息机制字典型探究(二) 带着这篇去通关所有Handler的提问(三)

Android消息机制:Looper,MessageQueue,Message与handler

Android消息机制好多人都讲过,但是自己去翻源码的时候才能明白. 今天试着讲一下,因为目标是讲清楚整体逻辑,所以不追究细节. Message是消息机制的核心,所以从Message讲起. 1.Message是什么? 看一个从消息池中取出一个msg的方法: public static Message obtain(Handler h, int what, int arg1, int arg2, Object obj) { Message m = obtain(); m.target = h; m

Android消息机制探索(Handler,Looper,Message,MessageQueue)

概览 Android消息机制是Android操作系统中比较重要的一块.具体使用方法在这里不再阐述,可以参考Android的官方开发文档. 消息机制的主要用途有两方面: 1.线程之间的通信.比如在子线程中想更新UI,就通过发送更新消息到UI线程中来实现. 2.任务延迟执行.比如30秒后执行刷新任务等. 消息机制运行的大概示意图如下: 一个线程中只能有一个Looper对象,一个Looper对象中持有一个消息队列,一个消息队列中维护多个消息对象,用一个Looper可以创建多个Handler对象,Han

Android消息机制1-Handler(Java层)(转)

转自:http://gityuan.com/2015/12/26/handler-message-framework/ 相关源码 framework/base/core/java/andorid/os/Handler.java framework/base/core/java/andorid/os/Looper.java framework/base/core/java/andorid/os/Message.java framework/base/core/java/andorid/os/Mes

Android消息机制Handler的实现原理解析

Android的主线程为什么可以一直存在? 线程是一个动态执行的过程,从产生到死亡包括五个状态:新建.就绪.运行.死亡和堵塞.只要线程没有执行完毕或者没有被其它线程杀死,线程就不会进入死亡状态.Android中的主线程一直存在是因为主线程中一直在监听消息,从而使线程无法被执行完毕. 线程的五种状态: 新建new Thread 当创建Thread类的一个实例对象时,此线程进入新建状态未被启动. 就绪runnable 线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等

Android 消息机制 (Handler、Message、Looper)

综合:http://blog.csdn.net/dadoneo/article/details/7667726 与 http://android.tgbus.com/Android/androidnews/201204/421642.shtml 一. 消息机制常用类的介绍和使用 在Android程序运行中,线程之间或者线程内部进行信息交互时经常会使用到消息,如果我们熟悉这些基础的东西及其内部的原理,将会使我们的Android开发变的容易.可以更好地架构系统.在学习Android消息机制之前,我们

Android消息机制Handler、Looper、MessageQueue源码分析

1. Handler Looper MessageQueue的关系 2.源码分析 下图表示了Handler.Looper.MessageQueue.Message这四个类之间的关系. Handler必须与一个Looper关联,相关Looper决定了该Handler会向哪个MessageQueue发送Message 每一个Looper中都包含一个MessageQueue Handler中的mQueue引用的就是与之关联的Looper的MessageQueue 不管Handler在哪个线程发送Mes

android消息机制原理详解

android消息机制原理详解 因为之前使用的是CSDN默认的文本编辑器,而且也因为懒得学用MarkDown来写博客,所以排版上有一些问题.就上一篇写的设计模式之抽象工厂模式提出了这个问题(一个android群的群友提出来的,没有在评论里评论),所以以后的文章都用MarkDown来写了. 好了,言归正传,这篇文章我来介绍一下android消息机制的原理 Android消息机制概述 说到Android的消息机制,Android初级工程师(不包括那些初学者)肯定会想到Handler.是的,Andro

网易视频云技术分享:Android 消息机制学习

Android消息机制大家都不陌生,想必大家也都看过Handler.Looper的源码(看过可以直接看末尾重点,一款监控APP卡顿情况的控件),下面,网易视频云技术专家就整合一下这方面的资料,加深对这方面的印象. 用法 private Handler mHandler = new Handler() {    @Override public void handleMessage(Message msg) {        switch (msg.what) {            case