Handler,Looper,Message,MessageQueue,HandlerThread使用总结(上)

在安卓程序中,经常会有一些耗时的操作例如下载,网络访问等,如果将这些放在主线程执行,会很耗时,这样可能会导致一个异常 叫ANR异常(Application Not Responding)将会阻塞UI线程,从而会导致程序无响应。因此我们会将一些耗时操作放在子线程进行,但是由于android的UI操作并不是线程安全的,因此如果多个线程同时操作UI的话,会导致线程安全问题,因此android制订了一条规则,只允许UI线程(即主线程)进行UI操作,那么我们如何知道子线程何时操作完成呢?例如子线程下载好图片以后通知主线程进行视图更新。

Message简介

子线程任务完成以后需要发送消息给主线程,这个消息就是Message的一个实例,定义Message时需要定义三个实例变量

1、what   int型消息代码,用来描述消息

2、obj      随消息发送的用户指定对象

3、target  处理该消息的Handler

创建Message的方法

1、new一个就行

2、使用Handler.obtainMessage(...)该方法可以使我们从公共循环池中获取到一个Message实例,效率会提高

因此我们使用该方法会好些

MessageQueue简介

MessageQueue(消息队列)用来存放Message,采用先进先出的方式发出Message,

Looper简介

Looper叫做消息循环,他会不断的检查 MessageQueue上是否有新消息,然后抓取消息,完成指定的任务。每个线程有且只有一个Looper对象,用来管理MessageQueue。主线程也有Looper,它会自动创建,主线程的所有工作都是由他的Looper完成的。Looper主要有两个方法

1、Looper.prepare     用以启用Looper

2、Looper.loop           让Looper开始工作,从消息队列中抓取处理消息

Handler简介

要处理消息以及消息指定的任务时就需要用到Handler,她可以发出新消息到MessageQueue上,也可以读取Looper从MessageQueue上获取的消息。一个Handler仅与一个Looper相关联,一个Message也仅与一个目标Hander相关联。

Handler发送消息的方法:

Looper获取到消息后,会交由消息的目标(即消息的target属性)处理,消息一般是在Handler.handleMessage(...)方法中处理

关系图示

在简单了解过这些知识后,我们写一个小程序,利用了Handler与Message。该应用的主界面仅有一个ImageView故代码不再给出,主要功能是开启一个子线程模拟下载图片,然后下载完成后在UI线程上进行更新。

主要代码

声明handler,模拟下载到的图片的资源Id数组

<span style="font-size:18px;"><pre name="code" class="java"><span style="font-size:18px;"><span style="white-space:pre">	</span>private ImageView mImageView;
	// 定义一个Handler
	private Handler mHandler;

	private int mIndex;
	// 存放照片资源id的数组
	int[] imageIds = new int[] { R.drawable.pic1, R.drawable.pic2,
			R.drawable.pic3, R.drawable.pic4

	};</span></span>

模拟下载图片的方法

<span style="font-size:18px;">// 模拟下载的操作,随机生成一个数字
	public int virtualDown() {
		Random ran = new Random();
		int value = ran.nextInt(5);
		return value;
	}</span>

使用TimerTask开启一个下载的子线程,获取到消息,并发送

<span style="font-size:18px;"><span style="font-size:18px;">// 开启一个TimerTask模拟下载的子线程
		new Timer().schedule(new TimerTask() {

			@Override
			public void run() {

				Bundle bundle = new Bundle();
				bundle.putInt("value", virtualDown());
				// 获取到消息
				// Message msg = new Message();
				Message msg = mHandler.obtainMessage();
				msg.what = 0x1233;
				msg.setData(bundle);
				// 发送消息,并将生成的数字传递过去
				mHandler.sendMessage(msg);

			}
		}, 0, 2000);
	}</span></span>

生成handle实例并在handleMessage中处理消息

<span style="font-size:18px;"><span style="white-space:pre">	</span>mHandler = new Handler() {

			@Override
			// 处理消息的方法
			public void handleMessage(Message msg) {
				// what属性是消息的标识,用来区分每个消息
				if (msg.what == 0x1233) {
					mIndex = msg.getData().getInt("value");
					// 设置图片的显示,这是在主线程进行的
					switch (mIndex) {
					case 0:
						mImageView.setImageResource(imageIds[0]);
						break;
					case 1:
						mImageView.setImageResource(imageIds[1]);
						break;
					case 2:
						mImageView.setImageResource(imageIds[2]);
						break;
					case 3:
						mImageView.setImageResource(imageIds[3]);
						break;
					}
				}
			}
		};</span>

运行程序我们就可以看到主界面的图片每隔两秒就会变化一次了,当然图片是事先准备好的,并非下载的,过段时间博主会实现真正的下载。

在上面的程序中为什么没有见到Looper呢?这是因为主线程在启动过程中自动创建了Looper。而子线程默认是不带Looper的,所以我们就需要自己创建Looper,这时候就需要用到上述的两个方法,Looper.prepare和Looper.loop启动Looper了,官方的API Demo的示例为:

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();
		}
	}
				
时间: 2024-08-24 09:00:31

Handler,Looper,Message,MessageQueue,HandlerThread使用总结(上)的相关文章

Handler,Looper,Message,MessageQueue之间关系浅析

一.先看一下使用流程 1.在子线程中使用Handler实例 /***********子线程使用Handler实例*********/ private class LooperThread extends Thread { public Handler handler; @Override public void run() { Looper.prepare(); handler = new Handler() { @Override public void handleMessage(Messa

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

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

Android异步消息处理 Handler Looper Message关系源码分析

# 标签: 读博客 对于Handler Looper Message 之前一直只是知道理论,知其然不知所以然,看了hongyang大神的源码分析,写个总结帖. 一.概念.. Handler . Looper .Message 这三者都与Android异步消息处理线程相关的概念. 异步消息处理线程启动后会进入一个无限的循环体之中,每循环一次,从其内部的消息队列中取出一个消息,然后回调相应的消息处理函数,执行完成一个消息后则继续循环.若消息队列为空,线程则会阻塞等待. 说了这一堆,那么和Handle

handler looper和messageQueue

一.使用方法. Looper用来处理消息循环,在创建过程中会初始化MessageQueue. Handler在其它线程发消息给当前线程 MessageQueue用来存放消息 Looper对象在哪个线程创建,Handler的handleMessage方法就在哪个线程执行 在创建activity时,android系统本身会为activity创建Looper. final Handler mainHandler = new Handler(getMainLooper()) { @Override pu

Android的Handler Looper Message机制应用实例与详解(二)

上一篇博文给出了Android中基于Handler Looper机制实现线程间通信的两个典型实例.本文将对该机制的基本原理进行较深入的研究.个人认为,学好Android编程最好的老师就是Android的源代码,下面将基于Android-19的源码进行分析,重点阐述分析思路. 要分析Handler Looper机制,自然想到去看Handler类和Looper类的源码(分别位于Handler.java和Looper.java两个文件中).简单阅读两个类的描述后,在Looper类的描述中能找到以下一段

Android的Handler Looper Message机制应用实例与详解(一)

Android的UI操作不是线程安全的(出于提高性能考虑,避免实现多线程同步等机制所引入的延时),若多个线程同时对UI元素进行操作,可能导致线程安全问题.因此,Android中做了严格的规定:只有UI主线程才能对UI进行设置与操作. 在实际编程中,为了避免UI界面长时间得不到响应而导致的ANR(Application Not Responding)异常,通常将网络访问.复杂运算等一些耗时的操作被放在子线程中执行.这就需要子线程在运行完毕后将结果返回到主线程并通过UI进行显示.在Android中,

Android 第十四课——Handler Looper Message

1.基础概念 1)android.os.Handler 2)主要接受子线程发送的数据, 并用此数据配合主线程更新UI. 3)应用程序一旦启动,Android UI 这个主线程的生命周期就开始了,然而,Android UI 线程并不是线程安全的,也就是说,更新UI只能在主线程中同步更新,子线程中异步操作是危险的.所以,项目中如果我们直接new Thread 内部去更改Android UI,往往会报错误如下: java.lang.RuntimeException: Can't create hand

Android好奇宝宝_09_Handler Looper Message

发现自己讲的东西都是UI相关的,这一篇就来讲讲Android很重要的知识点:Handler Looper Message. 废话少说,直接入正题. (1)存在的意义: 我一直把Handler Looper Message 这几个类当成几个可以搭配使用的工具类,特别之处在于系统提供了这些工具类,并且系统自己也使用了这些类. 既然是工具类,那么其功能是什么呢? 答:在当前线程建立一个唯一的消息队列,通过Handler可以向消息队列添加消息,Looper不断从消息队列取出消息,再转发给发送该消息的Ha

Android消息处理惩罚机制(Handler、Looper、MessageQueue与Message)

Android是消息驱动的,实现消息驱动有几个要素: (1)消息的默示:Message (2)消息队列:MessageQueue (3)消息轮回,用于轮回取出消息进行处理惩罚:Looper (4)消息处理惩罚,消息轮回从消息队列中取出消息后要对消息进行处理惩罚:Handler 日常平凡我们最常应用的就是Message与Handler了,若是应用过HandlerThread或者本身实现类似HandlerThread的器材可能还会接触到Looper,而MessageQueue是Looper内部应用的