解析Android的 消息传递机制Handler

1. 什么是Handler:

Handler 网络释义“操纵者,管理者的”意思,在Android里面用于管理多线程对UI的操作;

2. 为什么会出现Handler:

在Android的设计机制里面,只允许主线程(一个程序第一次启动时所移动的线程,因为此线程主要是完成对UI相关事件的处理,所以也称UI线程)

对UI进行修改等操作,这是一种规则的简化,之所以这样简化是因为Android的UI操作时线程不安全的,为了避免多个线程同时操作UI造成线程安全

问题,才出现了这个简化的规则。

由此以来,问题就出现了,因为只允许主线程修改UI,那么如果新线程的操作需要修改原来的UI该如何进行的?举个常见的例子就是:如果新线程的操作是更新UI中TextView

的值,那么该如何操作?

这时候就需要Handler在新线程和主线程(UI线程)之间传递休息;

3. Handler的功能:

主要就是两个:

1)在新启动的线程中发送消息;

2)在主线程中获取,处理消息;

看似简单,但是如何处理同步问题却是一个难题,即如何把握新线程发送消息的时机和主线程处理消息的时机。这个问题的解决方案是:

在主线程和新线程之间使用一个叫做MessageQueue的队列,新启动的线程发送消息时将消息先发送到与之关联的MessageQueue,然后主线程的Handler方法会被调用

从MessageQueue中去取相应的消息进行处理。

4. Handler的实现机制

Handler的实现主要是依靠下面的几个方法:

读取消息使用到的方法是;

void handleMessage(Message msg) ,进程通过重写这个方法来处理消息。

final boolean hasMessage(int what), 检查消息队列中是否包含what属性为指定值的消息。

final boolean hasMessage(int what,Object object),减产队列中是否有指定值和指定对象的消息。

Message obtainMessage(): 获取消息,课被多种方式重载。

发送消息用到的方法有:

sendEmptyMessage(int what): 发送空消息;

final boolean sendEmptyMessageDelayed(int what, long delayMillis):指定多少毫秒之后发送空消息

final boolean sendMessage(Message msg):立即发送消息

final boolean sendMessageDelayed(Message msg, long delayMillis)指定多少毫秒之后发送空消息

public class HandlerTest extends Activity
{
	ImageView show;
	// 代表从网络下载得到的图片
	Bitmap bitmap;
	Handler handler = new Handler()
	{
		@Override
		<span style="color:#ff0000;">public void handleMessage(Message msg)</span>
		{
			if(msg.what == 0x123)  //如果该消息是本程序发的
			{
				// 使用ImageView显示该图片
				show.setImageBitmap(bitmap);
			}
		}
	};
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		show = (ImageView) findViewById(R.id.show);
		<span style="color:#ff0000;">new Thread()</span>
		{
			public void run()
			{
				try
				{
					// 定义一个URL对象
					URL url = new URL("http://img001.21cnimg.com/photos"+
<span style="white-space:pre">					</span>"/album/20140626/o/C164BDB0B24F59929C2113C0A9910636.jpeg");
					// 打开该URL对应的资源的输入流
					InputStream is = url.openStream();
					// 从InputStream中解析出图片
					bitmap = BitmapFactory.decodeStream(is);
					// 发送消息、通知UI组件显示该图片
					<span style="color:#ff0000;">handler.sendEmptyMessage(0x123);</span>
					is.close();
				}
				catch (Exception e)
				{
					e.printStackTrace();
				}
			}
		}.start();
	}
}

新的进程在将图片从网上解析下来之后向主进程发送空消息,之后主线程中handleMessage()的方法会被自动调用,更新UI。

5.  深入理解Handler的工作机制

上面我们看到了一个简单的Handler的工作过程,其中Handler是在主线程中定义的。如果Handler是在子线程中定义的那么可以更深入的理解他的工作原理。

因为有的时候我们需要将主线程中的消息传递给子线程,让子线程去处理一些计算量比较大的任务,因为应用程序应尽量避免在UI线程中执行耗时操作,否则会

导致ANR异常(Application Not Responding)。这样的话,我们上面所讲的 主线程和新线程的角色就发生了颠倒,主线程需要向新线程发送消息,然后新线程

进行消息的处理。在这种情况下,Handler需要定义在新线程中,在这种情况下需要做一些额外的工作。

我们先来解释一下配合Handler的其它组件:

Looper: 每个线程对应一个looper,它负责管理MessageQueue,将消息从队列中取出交给Handler进行处理;

MessageQueue:负责管理Message,接收Handler发送过来的message;

下图是整个工作的流程:

下面我们具体阐述一下工作的过程:

在创建一个Handler之前需要先创建Looper,创建的方式是Looper.prepare();

在创建Looper的同时会自动创建MessageQueue;

下面 创建一个Handler的对象

然后调用Looper的loop()方法

下面的这段代码是一个实例,摘自 疯狂android讲义;主进程将上限发送给子线程计算2-上限之间的素数

public class CalPrime extends Activity
{
	static final String UPPER_NUM = "upper";
	EditText etNum;
	CalThread calThread;
	// 定义一个线程类
	class CalThread extends Thread
	{
		<span style="color:#cc0000;">public Handler mHandler;</span>

		public void run()
		{
			<span style="color:#ff0000;">Looper.prepare();</span>
			<span style="color:#ff0000;">mHandler = new Handler()</span>
			{
				// 定义处理消息的方法
				@Override
				public void handleMessage(Message msg)
				{
					if(msg.what == 0x123)
					{
						int upper = msg.getData().getInt(UPPER_NUM);
						List<Integer> nums = new ArrayList<Integer>();
						// 计算从2开始、到upper的所有质数
						outer:
						for (int i = 2 ; i <= upper ; i++)
						{
							// 用i处于从2开始、到i的平方根的所有数
							for (int j = 2 ; j <= Math.sqrt(i) ; j++)
							{
								// 如果可以整除,表明这个数不是质数
								if(i != 2 && i % j == 0)
								{
									continue outer;
								}
							}
							nums.add(i);
						}
						// 使用Toast显示统计出来的所有质数
						Toast.makeText(CalPrime.this , nums.toString()
							, Toast.LENGTH_LONG).show();
					}
				}
			};
			<span style="color:#ff0000;">Looper.loop();</span>
		}
	}
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		etNum = (EditText)findViewById(R.id.etNum);
		<span style="color:#ff0000;">calThread = new CalThread();</span>
		// 启动新线程
		<span style="color:#ff0000;">calThread.start();</span>
	}
	// 为按钮的点击事件提供事件处理函数
	public void cal(View source)
	{
		// 创建消息
		<span style="color:#ff0000;">Message msg = new Message();</span>
		msg.what = 0x123;
		Bundle bundle = new Bundle();
		bundle.putInt(UPPER_NUM ,
			Integer.parseInt(etNum.getText().toString()));
		<span style="color:#ff0000;">msg.setData(bundle);</span>
		// 向新线程中的Handler发送消息
		<span style="color:#ff0000;">calThread.mHandler.sendMessage(msg);</span>
	}
}

解析Android的 消息传递机制Handler,布布扣,bubuko.com

时间: 2024-10-25 20:53:38

解析Android的 消息传递机制Handler的相关文章

android线程消息传递机制——Looper,Handler,Message

android线程消息传递机制——Looper,Handler,Message 在引入这些概念之前,我们先了解一下引入这些机制的背景. 出于性能优化的考虑,Android的UI操作并不是线程安全的(如果你不懂什么是线程安全,可以阅读一下<一起探究多进程与多线程>里的数据安全与可重入),这意味着如果有多个线程同时操作某个UI组件,可能导致线程安全问题.为了解决这个问题,Android制定了一条简单的规则:只允许UI线程修改Activity里的UI组件.这个UI线程也通常被我们称为主线程. 在此引

Android异步消息传递机制源码分析&amp;&amp;相关知识常被问的面试题

1.Android异步消息传递机制有以下两个方式:(异步消息传递来解决线程通信问题) handler 和 AsyncTask 2.handler官方解释的用途: 1).定时任务:通过handler.postDelay(Runnable r, time)来在指定时间执行msg. 2).线程间通信:在执行较为耗时操作的时候,在子线程中执行耗时任务,然后handler(主线程的)把执行的结果通过sendmessage的方式发送给UI线程去执行用于更新UI. 3.handler源码分析 一.在Activ

Android的消息机制Handler详解

Android的消息机制详解 Android的消息机制主要指 Handler 的运行机制,Handler的运行需要底层的MessageQueue 和 Looper 的支撑. MessageQueue:消息队列,它的内部存储了一组消息,以队列的形式对外提供插入和删除的工作,其内部存储结构采用单链表的数据结构来存储消息列表. Looper:可理解为消息循环. 由于MessageQueue只是一个消息存储单元,不能去处理消息,而Looper会以无限循环的形式去查找是否有新的消息,如果有的话就处理,否则

Android Touch消息传递机制探究分析

在Android中,消息的传递控制主要是通过两个方法共同配合使用来对用户的触摸消息进行分发的,下面就来看看这两个方法: onInterceptTouchEvent:此方法定义于ViewGroup中,顾名思义,这个方法是用于ViewGroup拦截(intercept)触摸消息的: onTouchEvent:此方法定义于View中,用于处理用户的触摸事件: 下面来看这两个方法的定义原型: public boolean onInterceptTouchEvent(MotionEvent ev); pu

Android的消息处理机制——Looper,Handler和Message浅析

题外话: 说来有些惭愧,对于这三者的初步认识居然是在背面试题的时候.那个时候自己接触Android的时间还不长,学习的书籍也就是比较适合入门的<疯狂Android讲义>,当然在学到Handler这一部分的时候,书中也是有提到一些简单示例,后来在工作中需要用到这个MessageQueue的时候才开始真正琢磨了一下这三者的联系.如果想要对这三者好好理解一番,个人还是比较推荐<深入理解Android卷Ⅰ>.以下对这三者之间的恩怨纠葛的介绍和分析也是参考这本书的相关章节,算是一篇读书笔记吧

Android基础入门教程——3.3 Handler消息传递机制浅析

Android基础入门教程--3.3 Handler消息传递机制浅析 标签(空格分隔): Android基础入门教程 本节引言 前两节中我们对Android中的两种事件处理机制进行了学习,关于响应的事件响应就这两种:本节给大家讲解的 是Activity中UI组件中的信息传递Handler,相信很多朋友都知道,Android为了线程安全,并不允许我们在UI线程外操作UI:很多时候我们做界面刷新都需要通过Handler来通知UI组件更新!除了用Handler完成界面更新外,还可以使用runOnUiT

深入解析Android中Handler消息机制

Android提供了Handler 和 Looper 来满足线程间的通信.Handler先进先出原则.Looper类用来管理特定线程内对象之间的消息交换(MessageExchange).Handler消息机制可以说是Android系统中最重要部分之一,所以,本篇博客我们就来深入解析Android中Handler消息机制. Handler的简单使用 为什么系统不允许子线程更新UI 因为的UI控件不是线程安全的. 如果在多线程中并发访问可能会导致UI控件处于不可预期的状态,那为什么不对UI控件的访

Android笔记二十五.Android事件Handler消息传递机制

因为Android平台不同意Activity新启动的线程訪问该Activity里的界面控件.这样就会导致新启动的线程无法动态改变界面控件的属性值.但在实际Android应用开发中,尤其是涉及动画的游戏开发中,须要让新启动的线程周期性地改变界面控件的属性值,这就须要借助Handler的消息传递机制实现. 一.Handler类简单介绍 1.功能 Handler类主要有两个作用 (1)在新启动的线程中发送消息; (2)在主线程中获取消息.处理消息.即当须要界面发生变化的时候.在子线程中调用Handle

Android消息机制Handler解析(源码+Demo)

Handler是开发人员在面试过程中最常见的问题之一了,这篇文章将较为全面地对Handler进行解读,包括源码层,以及使用方法. 如果看完文章有疑问,欢迎在评论中一起探讨 基本内容包括: 看完文章之后,可以用这个图片进行复习. 一.什么是Handler Handler是Android提供用来更新UI的一套机制,也是一套消息处理机制,可以用它来发送消息,也可以用它来接收消息. 二.为什么使用Handler Android在设计之时,就封装了一套消息的创建.传递.处理机制,若不遵循这样的处理机制,就