基于消息队列的线程通信:
          消息队列与线程循环
          

MessageQueue:     
     利用链表来管理消息。
     
          

Message:


     通常由Handler的子类的handleMessage()函数来处理该消息。


由android.os.Handler类来处理消息Message:
     
Handler:
     由Handler来处理消息,由其函数dispatchMessage()完成。
    public void dispatchMessage(Message msg) {

if (msg.callback != null) {

            handleCallback(msg);

        } else {

            if (mCallback != null) {

                if (mCallback.handleMessage(msg)) {

                    return;

                }

            }

            handleMessage(msg); //若消息没有指定处理消息的对象,则由Handler的子类来完成。其子类必须实现handleMessage()方法。

        }

    }




Looper:

     Looper与线程关联,一个线程最多有一个Looper。Looper实例保存到宿主线程的线程局部存储中。

     指定了Looper就意味着指定了在哪个线程中处理;为消息指定的Handler则决定如何处理消息。
     
     Looper中拥有一个消息队列MessageQueue,该消息队列由Looper创建,属于它所有。

    private Looper(boolean quitAllowed) {

        mQueue = new MessageQueue(quitAllowed);//创建Looper要处理的消息队列,是否运行线程退出,由消息队列决定。

        mRun = true;

        mThread = Thread.currentThread();//得到当前线程

    }

    public static void loop() {

        final Looper me = myLooper();

        if (me == null) {

            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");

        }

        final MessageQueue queue = me.mQueue;



        // Make sure the identity of this thread is that of the local process,

        // and keep track of what that identity token actually is.

        Binder.clearCallingIdentity();

        final long ident = Binder.clearCallingIdentity();



        for (;;) {

            Message msg = queue.next(); // might block//取得一个消息

            if (msg == null) {//消息体为空则表示退出

                // No message indicates that the message queue is quitting.

                return;

            }



            // This must be in a local variable, in case a UI event sets the logger

            Printer logging = me.mLogging;

            if (logging != null) {

                logging.println(">>>>> Dispatching to " + msg.target + " " +

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

            }



            msg.target.dispatchMessage(msg);//调用消息指定的接收者Handler来处理它



            if (logging != null) {

                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);

            }



            final long newIdent = Binder.clearCallingIdentity();

            if (ident != newIdent) {

                Log.wtf(TAG, "Thread identity changed from 0x"

                        + Long.toHexString(ident) + " to 0x"

                        + Long.toHexString(newIdent) + " while dispatching to "

                        + msg.target.getClass().getName() + " "

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

            }



            msg.recycle();//丢弃消息,循环再利用

        }

    }


Handler:消息的处理者。一旦为消息指定了某个特定的处理者Handler,也就确定了在哪个线程的上下文中去处理以及如何处理消息。

          实际上是根据Handler的变量mLooper所代表的Looper所在的线程,来决定该Handler运行在哪个线程中。

         在一个线程中创建的Handler并不一定运行在该线程中,需要判断该Handler的Looper变量在哪个线程中。

       public Handler() {

if (FIND_POTENTIAL_LEAKS) {

            final Class<? extends Handler> klass = getClass();

            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&

                    (klass.getModifiers() & Modifier.STATIC) == 0) {

                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +klass.getCanonicalName());

            }

        }



        mLooper = Looper.myLooper();//通过线程局部存储,获得本线程的Looper:当程序没有另启一个线程时,该Looper就是主线程的Looper。

          

        if (mLooper == null) {

            throw new RuntimeException(

                "Can't create handler inside thread that has not called Looper.prepare()");

        }

        mQueue = mLooper.mQueue;

        mCallback = null;

    }



         public void dispatchMessage(Message msg) {

if (msg.callback != null) {

            handleCallback(msg);//消息所指定的CallBack,实际就是Runnable

        } else {

            if (mCallback != null) {

                if (mCallback.handleMessage(msg)) {

                    return;

                }

            }

            handleMessage(msg);//Handler的方法

        }

    }

android消息线程和消息队列的更多相关文章

  1. android 进程/线程管理(一)----消息机制的框架

    一:android 进程和线程 进程是程序运行的一个实例.android通过4大主件,弱化了进程的概念,尤其是在app层面,基本不需要关系进程间的通信等问题. 但是程序的本质没有变,尤其是多任务系统, ...

  2. android 进程/线程管理(四)续----消息机制的思考(自定义消息机制)

    继续分析handler 和looper 先看看handler的 public void dispatchMessage(Message msg) { if (msg.callback != null) ...

  3. android 进程/线程管理(四)----消息机制的思考(自定义消息机制)

    关于android消息机制 已经写了3篇文章了,想要结束这个系列,总觉得少了点什么? 于是我就在想,android为什么要这个设计消息机制,使用消息机制是现在操作系统基本都会有的特点. 可是andro ...

  4. Android源码分析-消息队列和Looper

    转载请注明出处:http://blog.csdn.net/singwhatiwanna/article/details/17361775 前言 上周对Android中的事件派发机制进行了分析,这次博主 ...

  5. android handle详解2 主线程给子线程发送消息

    按照android handler详解分析的原理我们可以知道,在主线程中创建handle对象的时候,主线程默认创建了一个loop对象使用threalocal函数将loop对象和主线程绑定. 我们能不能 ...

  6. 深入浅出Win32多线程设计之MFC的多线程-线程与消息队列(经典)

    1.创建和终止线程 在MFC程序中创建一个线程,宜调用AfxBeginThread函数.该函数因参数不同而具有两种重载版本,分别对应工作者线程和用户接口(UI)线程. 工作者线程 CWinThread ...

  7. Android:子线程向UI主线程发送消息

    在Android里,UI线程是不同意被堵塞的.因此我们要将耗时的工作放到子线程中去处理. 那么子线程耗时处理后要如何通知UI线程呢? 我们能够在UI主线程中创建一个handler对象,然后通过重写其h ...

  8. python 实现多个线程间消息队列传递,一个简单的列子

    #-*-coding:utf8-*-"""Producer and consumer models: 1. There are many producers and co ...

  9. Android笔记(三十二) Android中线程之间的通信(四)主线程给子线程发送消息

    之前的例子都是我们在子线程(WorkerThread)当中处理并发送消息,然后在主线程(UI线程)中获取消息并修改UI,那么可以不可以在由主线程发送消息,子线程接收呢?我们按照之前的思路写一下代码: ...

随机推荐

  1. JavaScript调试技巧之console.log()

    与alert()函数类似,console.log()也可以接受变量并将其与别的字符串进行拼接: 代码如下: //Use variable var name = "Bob"; con ...

  2. 【DP】区间DP入门

    在开始之前我要感谢y总,是他精彩的讲解才让我对区间DP有较深的认识. 简介 一般是线性结构上的对区间进行求解最值,计数的动态规划.大致思路是枚举断点,然后对断点两边求取最优解,然后进行合并从而得解. ...

  3. 编程方式建视频——GitHub 热点速览 v.21.07

    作者:HelloGitHub-小鱼干 假期过半,大家过得如何,吃好喝好了吗?GitHub 很好!本周的 GitHub Trending 又上爆款项目--github1s 装完之后,一秒 GitHub ...

  4. 手把手搭建一套基于 Sentry 的异常监控系统

    手把手搭建一套基于 Sentry 的异常监控系统 Sentry 开源版 DevOps refs https://github.com/getsentry/sentry sentry-anomaly-m ...

  5. i18n 和 L10n (internationalization and localization) 国际化与本地化(具有全球战略眼光的公司企业的必由之路)

    i18n 和 L10n (internationalization and localization)  国际化与本地化(具有全球战略眼光的公司企业的必由之路) 1 1 https://zh.wiki ...

  6. Android 如何使用 WebView 加载 HTML 字符串和处理转译字符

    Android 如何使用 WebView 加载 HTML 字符串和处理转译字符 css bug 在 WebView 中编译 Web 应用 如果您希望在客户端应用中提供 Web 应用(或只是网页),则可 ...

  7. HTML5 download 执行条件

    HTML5 download 执行条件 同一个域名下的资源 http only 绝对路径/相对路径 都可以 demo https://cdn.xgqfrms.xyz/ https://cdn.xgqf ...

  8. 1+X 证书制度

    1+X 证书制度 教育部职业技术教育 http://www.cvae.com.cn/zgzcw/tzgg/202001/c0ddd6c87e6c42839f8cc3e09a2dce89.shtml 2 ...

  9. Python & file operation mode

    Python & file operation mode create/read/write/append mode https://docs.python.org/3/library/fun ...

  10. VIM 官方教程

    VIM 官方教程 zh-hans vim official documents https://www.vim.org/docs.php https://vimhelp.org/ translatio ...