1. 消息处理类——Handler 

  消息处理类(Handler)允许发送和处理Message或Runnable对象到其所在线程的MessageQueue中。Handerl有以下两个主要作用:

  1. 将Message或Runnable应用post()方法或sendMessage()方法发送到MessageQueue中,在发送时可以指定延迟时间、发送时间或者要携带的Bundle数据。当MessageQueue循环到该Message时,调用相应的Handler对象的handlerMessage()方法对其进行处理。
  2. 在子线程中与主线程进行通信,也就是在工作线程中与UI线程进行通信。

  说明:在一个线程中,只能有一个Looper和MessageQueue,但是,可以有多个Handler,而且这些Handler可以共享同一个Looper和MessageQueue。

Handler类提供的常用方法

方法  描述
handleMessage(Message msg) 处理消息的方法。通常重写该方法来处理消息,在发送消息时,该方法会自动回调。
post(Runnable r) 立即发送Runnable对象,该Runnable对象最后将被封装成Message对象
postAtTime(Runnable r, long uptimeMillis) 定时发送Runnable对象,该Runnable对象最后将被封装成Message对象
postDelayed(Runnable r, long delayMillis)

延迟多少毫秒发送Runnable对象,该Runnable对象最后将被封装成Message对象

sendEmptyMessage(int what) 发送空消息
sendMessage(Message msg) 立即发送消息
sendMessageAtTime(Message msg, long uptimeMillis) 定时发送消息
sendMessageDelayed(Message msg, long delayMillis) 延迟多少毫秒发送消息

2. 消息类——Message

  消息类(Message)被存放在MessageQueue中,一个MessageQueue中可以包含多个Message对象。每个Message对象可以通过Message.obtain()方法或者Handler.obtainMessage()方法获得。一个Message对象具有下表所示的5个属性。

Message类的属性

属性 类型 描述
arg1 int 用来存放整型数据
arg2 int 用来存放整型数据
obj Object 用来存放发送给接收器的Object类型的任意对象
replyTo Messenger 用来指定此Message发送到何处的可选Messager对象
what int 用于指定用户自定义的消息代码,这样接收者可以了解这个消息的信息

  说明:使用Message类的属性可以携带int型的数据,如果要携带其他类型的数据,可以先将要携带的数据保存到Bundle对象中,然后通过Message类的setDate()方法将其添加到Message中。

  综上所述,Message类的使用方法比较简单,只要在使用它时,注意以下3点即可:

  • 尽管Message有public的默认构造方法,但是通常情况下,需要使用Message.obtain()方法或Handler.obtainMessage()方法来从消息池中获得空消息对象,以节省资源。
  • 如果一个Message只需要携带简单的int型信息,应优先使用Message.arg1和Message.arg2属性来传递信息,这比用Bundle更省内存。
  • 尽可能使用Message.what来标识信息,以便用不同的方式处理Message。

3. 用Handler和Message实现一个每隔1秒更新时间的程序

1. 布局文件activity_main.xml内容如下

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.tiaoshi.MainActivity" > <TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="每秒变化的文本" />
<Button
android:id= "@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/start" />
<Button
android:id="@+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/stop" /> </LinearLayout>

2. MainActivity内容如下

package com.example.tiaoshi;

import java.util.Date;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView; public class MainActivity extends ActionBarActivity implements Runnable {
private Button startBtn = null;
private Button stopBtn = null;
private Thread thread = null;
private Handler handler = null;
private TextView text = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.text = (TextView) this.findViewById(R.id.text);
//处理消息
handler = new Handler(){ @Override
public void handleMessage(Message msg) {
if(msg.what==0x101){
text.setText("当前时间为:"+new Date());
}
super.handleMessage(msg);
} };
this.startBtn = (Button) this.findViewById(R.id.btn1);
startBtn.setOnClickListener(new OnClickListener(){ @Override
public void onClick(View arg0) {
thread = new Thread(MainActivity.this);
thread.start();
text.setText("当前时间为:"+new Date());
} });
this.stopBtn = (Button) this.findViewById(R.id.btn2);
stopBtn.setOnClickListener(new OnClickListener(){ @Override
public void onClick(View arg0) {
if(thread!=null){
thread.interrupt();
thread = null;
}
Log.i("提示", "中断线程");
} });
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
} @Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
} @Override
public void run() {
try {
while(!Thread.currentThread().isInterrupted()){
Message m = handler.obtainMessage(); //获取一个空的message
m.what = 0x101; //设置消息标识
handler.sendMessage(m); //发送消息
Thread.sleep(1000);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } @Override
protected void onDestroy() {
if(thread!=null){
thread.interrupt();
thread = null;
}
super.onDestroy();
}
}

4. 创建Handler对象发送并处理消息

  在Eclipse中创建Android项目,创建一个继承了Thread类的LooperThread,并在重写的run()方法中,创建一个Handler对象并处理消息。

  在Android中,一个线程对应一个Looper对象,而一个Looper对象又对应一个MessageQueue(消息队列)。MessageQueue用于存放Message(消息),在MessageQueue中,存放的消息按照FIFO(先进先出)原则执行,由于MessageQueue被封装到Looper里面了,所以这里不对MessageQueue进行过多介绍。

  Looper对象用来为一个线程开启一个消息循环,用来操作MessageQueue。默认情况下Android中新创建的线程是没有开启消息循环的。但是主线程除外,系统自动为主线程创建Looper对象,开启消息循环。所以,当我们在主线程中,应用下面的代码创建Handler对象时,就不会出错,而如果在创建的非主线程中,应用下面的代码创建Handler对象时,将产生异常信息。

Handler handler = new Handler(); 

  如果想要在非主线程中,创建Handler对象,首先需要使用Looper类的prepare()方法来初始化一个Looper对象,然后创建这个Handler对象,再使用Looper类的loop()方法启动Looper,从消息队列里获取和处理消息。

  Looper类提供的常用方法如下表所示。

方法 描述
prepare() 用于初始化Looper
loop() 调用loop()方法后,Looper线程就开始真正工作了,它会从消息队列里获取消息和处理消息
myLooper() 可以获取当前线程的Looper对象
getThread() 用于获取Looper对象所属的线程
quit() 用于结束Looper循环

  注意:写在Looper.loop()之后的代码不会被执行,这个函数内部是一个循环,当调用Handler.getLooper().quit()方法后,loop()方法才会终止,其后面的代码才能得以执行。

1. 创建一个继承了Thread类的LooperThread,并在重写的run()方法中,创建一个Handler对象发送并处理消息,关键代码如下:

package com.example.tiaoshi;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log; public class LooperThread extends Thread {
public Handler handler; //声明一个Handler对象
@Override
public void run() {
super.run();
Looper.prepare(); //初始化Looper对象
//实例化一个Handler对象
handler = new Handler(){ @Override
public void handleMessage(Message msg) {
Log.i("Looper", String.valueOf(msg.what));
} };
//获取一个消息
Message m = handler.obtainMessage();
//设置Message的what属性的值
m.what = 0x11;
// 发送消息
handler.sendMessage(m);
//启动Looper
Looper.loop();
} }

2. 在MainActivity的onCreate()方法中,创建一个LooperThread线程,并开启该线程,关键代码如下:

    protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LooperThread thread = new LooperThread(); //创建一个线程
thread.start(); //开启线程
}

与多线程结合使用的消息处理类Handler、Message的更多相关文章

  1. Android多线程编程<二>Handler异步消息处理机制之Message

      Message(消息):       一. Message的字段:    在Android中,Message作为线程之间(主要是子线程和UI主线程之间)数据交换的载体,通过Handler去传递.它 ...

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

    Android是消息驱动的,实现消息驱动有几个要素: 消息的表示:Message 消息队列:MessageQueue 消息循环,用于循环取出消息进行处理:Looper 消息处理,消息循环从消息队列中取 ...

  3. android的消息处理机制——Looper,Handler,Message

    在开始讨论android的消息处理机制前,先来谈谈一些基本相关的术语. 通信的同步(Synchronous):指向客户端发送请求后,必须要在服务端有回应后客户端才继续发送其它的请求,所以这时所有请求将 ...

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

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

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

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

  6. 从Handler+Message+Looper源代码带你分析Android系统的消息处理机制

    PS一句:不得不说CSDN同步做的非常烂.还得我花了近1个小时恢复这篇博客. 引言 [转载请注明出处:http://blog.csdn.net/feiduclear_up CSDN 废墟的树] 作为A ...

  7. java多线程并发去调用一个类的静态方法安全性探讨

    java多线程并发去调用一个类的静态方法安全性探讨 转自:http://blog.csdn.net/weibin_6388/article/details/50750035   这篇文章主要讲多线程对 ...

  8. 【Java多线程系列五】列表类

    一些列表类及其特性  类 线程安全 Iterator 特性 说明 Vector 是 fail-fast 内部方法用synchronized修饰,因此执行效率较低 1. 线程安全的列表类并不意味着调用它 ...

  9. Android Handler处理机制 ( 二 ) ——Handler,Message,Looper,MessageQueue

    Android是消息驱动的,实现消息驱动有几个要素: 消息的表示:Message 消息队列:MessageQueue 消息循环,用于循环取出消息进行处理:Looper 消息处理,消息循环从消息队列中取 ...

随机推荐

  1. 9 行 javascript 代码获取 QQ 群成员

    昨天看到一条微博:「22 行 JavaScript 代码实现 QQ 群成员提取器」. 本着好奇心点击进去,发现没有达到效果,一是 QQ 版本升级了,二是博客里面的代码也有些繁琐. 于是自己试着写了一个 ...

  2. 【ASP.NET MVC】Scripts目录

    很多时候我们经常在用的东西我们可能不一定真正的了解,因为我们可能已经会用了,便不再对其进行探索,下面我们看一下在ASP.NET MVC3项目下的Scripts目录下的文件: Jquery核心库我们就不 ...

  3. NHibernate示例

    1. 下载相关资源: 下载NHibernate.下载地址: http://nhforge.org/Default.aspx 下载微软Northwind示例数据库,下载地址:http://www.mic ...

  4. [Gym - 100517K] Kingdom Division 2 二分

    大致题意: 给出一个凸包,以及凸包内的两个点p1,p2,求有多少条经过凸包顶点的直线能够将凸包分割为两部分,且给出的两点分别属于不同的部分 枚举凸包的顶点,二分求出p1,p2线段左边的最大坐标L以及右 ...

  5. java自定义类

    引用数据类型(类) 引用数据类型分类 提到引用数据类型(类),其实我们对它并不陌生,之前使用过的Scanner类.Random类. 我们可以把类的类型为两种: 第一种,Java为我们提供好的类,如Sc ...

  6. 剖析ironic

    关键技术 在安装操作系统时需要存储介质来存储系统镜像.需要控制物理机开关机,在网络部署环境中还需要预启动环境. PXE (预启动环境) IPMI(电源管理) iSCSI(存储) 什么是PXE PXE( ...

  7. WSDL语法

    <什么是WSDL语言> WSDL(网络服务描述语言,Web Services Description Language)是一门基于 XML 的语言,用于描述 Web Services 以及 ...

  8. 安卓 onTouch OnTouchEvent onChick 顺序

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha 分发触摸事件 -> 在 触摸 时候 -> 在触摸事件时候->在点击时候 ...

  9. [APIO2007]风铃 --- 贪心

    [APIO2007]风铃 题目描述 你准备给弟弟 Ike 买一件礼物,但是,Ike 挑选礼物的方式很特别:他只喜欢那些能被他排成有序形状的东西. 你准备给 Ike 买一个风铃.风铃是一种多层的装饰品, ...

  10. [CodeForces-440D]Berland Federalization

    题目大意: 给你一棵树,你可以删掉一些边,使得分除去的子树中至少有一棵大小为k. 问最少删去多少边,以及删边的具体方案. 思路: 树形DP. f[i][j]表示以i为根,子树中去掉j个点最少要删边的数 ...