1. Android消息处理机制: Handler, MessageQueue, Looper, Thread

线程概念 : 一个应用程序运行时它的主体被称为进程,
一个进程内部可以有多个线程,
线程共享进程的资源 
线程间通信

在android系统中是怎么封装通讯的,假如存在两个线程A和B,如果A线程要告诉B线程一些消息,怎么实现?

A进程怎么发发消息?(1)构造消息,消息里面有数据信息和处理函数(2)发消息;这两个步骤在android源码中被封装成Handler

消息在android中被封装为Message,A发送Message给B,可能B处理不过来,因此A把消息放到B进程里面的消息队列MessageQueue类,在B进程的循环体中做什么事?

(1)、从队列中取出消息;(2)处理消息,执行消息的处理函数;这两个步骤在android源码中被封装成Looper

Looper源码在frameworks/base/core/java/android/os/Looper.java

Handler源码在frameworks/base/core/java/android/os/Handler.java   //ctrl+shift+n在输入handler.java来打开

a. 创建MessageQueue: Looper.prepare()
b. 使用Handler构造、发送Message
b.1 new Handler  //创建handler的时候可以指定Looper即消息接受者和Callback回调函数即消息的处理函数,如果不知道肯定有默认的Looper和消息处理函数
b.2 Handler.sendMessage, sendEmptyMessageAtTime, sendMessageDelayed

c. 使用Looper循环处理消息:在loop函数中有个for死循环
c.1 从MessageQueue中取出Message,//Message msg = queue.next();
c.2 执行它的处理函数: msg.target.dispatchMessage(msg)//target就是Handler,dispatchMessage会调用处理函数

  

应用程序编写:

功能说明:app中创建一个button,创建子线程,添加消息处理功能,并且给Button添加处理函数,并且主线程会监测button,当button按下时给子线程发送消息,子线程收到消息后打印出来

import android.view.View;

import android.util.Log;//打印导入的库

public class MainActivity extends AppCompatActivity{

  private Button mButton;

  private final String TAG = "MessageTest";

  private int ButtonCount = 0;

  private Thread myThread;

  private MyThread myThread2;

  private Handler mHandler;

  private int mMessageCount = 0;

  class MyRunnable:implements Runable{

    int count=0;

    public void run(){

      for(;;){

        Log.d(TAG,"MyThread"+(count++));

        try{  

          Thread.sleep(3000);

        }catch(INterrupteException e){

          e.printStackTrace();

        }

      }

    }

  }

  class Mythread extends Thread{       //android只带的消息处理是在HandlerThread.java中,其功能同我们怎么的Mythread,如果不自己创建Mythread,可以直接使用HandlerThread类

    public void run(){

      super.run();

      Looper.prepare();//创建消息队列

      Looper.loop();//从消息队列中取出消息,调用消息的处理函数

    }

    public Looper getLooper(){

      return Looper.myLooper();

    }

  }

  pretected void onCreate(Bundle savedInstanceState){

    ........

    ........

    mButton = (Button)findViewById(R.id.button);//双击Button,按下shift+F1,可以查看类的帮助文档

    mButton.setOnClickListener(new View.OnClickListener(){

      public void onClick(View v){

        Log.d(TAG,"SendMessage"+(ButtonCount++) );

        Message msg = new Message();

        mHandler.sendMessage(msg );//发送消息的会从把消息放到消息队列中,消息队列是从handler创建的时候从Looper中获得

      }

    });

    myThread = new Thread(new MyRunnable,"MessageTestThread");//(runnable接口的方法run是线程的主体函数)

    myThread.start();

    myThread2 = new MyThread();

    myThread2 .start();//功能和myThread一样,start会导致MyThread的run函数被执行,run函数会执行Looper.prepare()去创建消息队列,但这个函数并不一定马上就执行,如果住进程中创建Handler的时候没有队列,会存在风险,所以修改class MyThread extends Thread{}

    ////我们现在的代码里面有三个线程了,主线程、myThread和myThread2,,要确定消息发给谁Looper

    mHandler = new Handler(myThread2.getLooper(),new Handler.Callback(){

      public boolean handleMessage(Message msg){

        Log.d(TAG,"getMessage"+(mMessageCount++))

        return false;

      }

    });

  }

}

针对上面所说的风险修改class MyThread extends Thread{},如下:

class MyThread extends Thread{

  private Looper mLooper;

    public void run(){

      super.run();

      Looper.prepare();//创建消息队列

      mLooper = Looper.myLooper();

      notifyAll();//当主线程调用getLooper,在mLooper 为空的时候会休眠,所以这里需要唤醒休眠的线程

      Looper.loop();//从消息队列中取出消息,调用消息的处理函数

    }

    public Looper getLooper(){

      if(!isAlive()){

        return null;

      }

      synchronized(this){

        while(isAlive() && mLooper == null){

          try{

            wait();

          }catch (InterruptedException e){

          }

        }

      }

      return mLooper;

    }

}

修改代码使用系统只带的消息处理线程:

1、导入包:import android.os.HandlerThread;

2、在public class MainActivity extends AppCompatActivity中新增

  private HandlerThread myThread3;

  private Handler mHandler3;

  myThread3 = new HandlerThread("MessageTestThread3");

  myThread3 .start();

  mHandler3 = new Handler(myThread3.getLooper());

  在button的onClick函数中添加:

  mHandler3.post(new Runnable(){

    public void run(){

      Log.d(TAG,"getMessage for Thread3"+(mMessageCount++));

    }

  });

  

7.1 基础知识Android消息处理机制的更多相关文章

  1. 【Android 开发】: Android 消息处理机制之一: Handler 与 Message

    最近几讲内容,我们学习了Android中关于多线程的一些知识,上一讲我们讲解了异步任务 AsyncTask 的操作,Android中还提供了其他的线程操作,如Handler Message Messa ...

  2. (转)Android消息处理机制(Handler、Looper、MessageQueue与Message)

    转自 http://www.cnblogs.com/angeldevil/p/3340644.html Android消息处理机制(Handler.Looper.MessageQueue与Messag ...

  3. Android消息处理机制

    Android消息处理机制 Android应用程序消息处理机制(深入到native,实际由管道实现-pipe&epoll)

  4. 解析Android消息处理机制:Handler/Thread/Looper & MessageQueue

    解析Android消息处理机制 ——Handler/Thread/Looper & MessageQueue Keywords: Android Message HandlerThread L ...

  5. Android架构分析之Android消息处理机制(二)

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android版本号:4.4.2 在上一篇文章中我们看了一个使用Handler处理Message消息的样例,本文我们 ...

  6. Android架构分析之Android消息处理机制(一)

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android版本号:4.4.2 在这个系列文章中我们将来分析Android消息处理机制. 本文介绍了一个使用Han ...

  7. Android消息处理机制(Handler 与Message)---01

    一.handler的使用场景为么会有handler?(部分内容图片摘自http://www.runoob.com/w3cnote/android-tutorial-handler-message.ht ...

  8. [旧][Android] 消息处理机制

    备注 原发表于2016.06.06,资料已过时,仅作备份,谨慎参考 概述 Android 的消息处理机制主要是指 Handler 的运行机制以及 Handler 所附带的 MessageQueue 和 ...

  9. 【Android】Android消息处理机制

    三大核心类 android的消息处理有三个核心类:Looper,Handler和Message. 其实还有一个Message Queue(消息队列),但是MQ被封装到Looper里面了 Looper ...

随机推荐

  1. php intval函数

    php intval函数 作用 intval — 获取变量的整数值 使用实例 <?php echo intval('-42'); // -42 ?> 相似函数 boolval() - 获取 ...

  2. 刘汝佳 算法竞赛-入门经典 第二部分 算法篇 第六章 2(Binary Trees)

    112 - Tree Summing 题目大意:给出一个数,再给一颗树,每个头节点的子树被包含在头节点之后的括号里,寻找是否有从头节点到叶子的和与给出的数相等,如果有则输出yes,没有输出no! 解题 ...

  3. 突破极限 解决大硬盘上安装Unix新思路

    一.问题提出 硬盘越做越大,然我喜欢让我忧.10年前就遇到过在586电脑BIOS不认识超过8.4G容量硬盘的问题,以及Windows Nt操作系统不认大硬盘(容量超过8.4G)的问题,对于Linux ...

  4. Android 将HTML5封装成android应用APK文件的几种方法

    越来越多的开发者热衷于使用html5+JavaScript开发移动Web App.不过,HTML5 Web APP的出现能否在未来取代移动应用,就目前来说,还是个未知数.一方面,用户在使用习惯上,不喜 ...

  5. Kinect 开发 —— 语音识别(上)

    Kinect的麦克风阵列在Kinect设备的下方.这一阵列由4个独立的水平分布在Kinect下方的麦克风组成.虽然每一个麦克风都捕获相同的音频信号,但是组成阵列可以探测到声音的来源方向.使得能够用来识 ...

  6. Linux下设置ip和主机名进行绑定

    1:输入命令gedit   /etc/hosts 这样你就打开了一个文本,然后在文本的末尾进行加入例如以下: ip地址                主机名 192.168.0.125       h ...

  7. 【剑指Offer学习】【面试题49:把字符串转换成整数】

    题目:实现一个函数stringToInt,实现把字符串转换成整数这个功能.不能使用atoi或者其它相似的库函数. 题目解析 这看起来是非常easy的题目,实现基本功能 ,大部分人都能用10行之内的代码 ...

  8. VPS搭建与IPv6使用教程

    VPS搭建与IPv6使用教程 SoftEther命令: yum -y install gcc zlib-devel openssl-devel readline-devel ncurses-devel ...

  9. 取消cp命令别名

    1. 取消cp命令别名unalias cpcp -rf恢复别名alias cp='cp -i'2.关闭当前用户下的cp别名配置sed -i "s/alias cp='cp -i'/#alia ...

  10. [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.0:compile (default-compile) 问题解决

    问题描述详情: 无论你的问题是3.0还是3.1还是任何一个版本,则都可以通过以下版本来解决 解决办法: 把默认的Internal JRE改成了JAVA_HOME. 运行后成功了,截图如下: