• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > Handler消息传递机制(一)

Handler消息传递机制(一)

作者:网友 字体:[增加 减小] 来源:互联网 时间:2017-05-26

网友通过本文主要向大家介绍了handler消息传递机制,handler消息机制,handler消息机制原理,handler发送消息,handler移除消息等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

Handler消息传递机制(一)


为什么要用Handler:

出于性能优化考虑,Android的UI操作并不是线程安全的,这意味着如果有多个线程并发操作UI组件,可能导致线程安全问题。为了解决这个问题,Android制定了一条简单的原则:只允许UI线程(亦即主线程)修改Activity中的UI组件。
当一个程序第一次启动时,Android会同时启动一条主线程,主线程主要负责处理与UI相关的事件,如用户的按键事件、用户接触屏幕的事件、屏幕绘图事件,并把相关的事件分发到相应的组件进行处理,所以主线程通常又叫做UI线程。

Handler的概念:

1)执行计划任务,可以在预定的时间执行某些任务,可以模拟定时器
2)线程间通信。在Android的应用启动时,会创建一个主线程,主线程会创建一个

消息队列来处理各种消息。当你创建子线程时,你可以在你的子线程中拿到父线程中
创建的Handler 对象,就可以通过该对象向父线程的消息队列发送消息了
。由于Android要求在UI线程中更新界面,因此,可以通过该方法在其它线程中更新界面。

Handler类包含如下方法用于发送、处理消息:

? void handlerMessage(Message msg):处理消息的方法,该方法通常用于被重写。
   ? final boolean hasMessage(int what):检查消息队列中是否包含what属性为指定值的消息。
? sendEmptyMessage(int what):发送空消息
? final boolean sendMessage(Message msg):立即发送消息,注意这块返回值,如果message成功的被放到message queue里面则返回true,反之,返回false;(个人建议:对于这类问题不必主观去记它,当实际使用时,直接查看源码即可,源码中有详细的注释)

Handler的作用:
(1)在一个线程中发送消息。
(2)在另一个线程中获取、处理消息。
Handler处理的基本原理:

为了让主线程能及时处理子线程发送的消息,显然只能通过回调的方法来实现----开发者只要重写Handler类中的方法,当新启动的线程发送消息时,消息会发送至与之关联的MessageQueue,而Handler会不断的从MessageQuere中获取并处理消息-----这将导致Handler类中处理消息的方法被回调。
在线程中使用Handler的基本步骤如下:
在被调用线程中完成以下内容:
(1)调用 Looper的prepare()方法为当前线程创建Looper对象,创建Looper对象时,它的构造器会创建与之配套的MessageQueue。
(2)有了Looper之后,创建Handler子类的实例,重写HandlerMessage()方法,该方法负责处理来自其它线程的消息。
(3)调用Looper的loop()方法启动Looper。

注:若被调用线程是主线程类,由于系统自动为主线程创建了Looper的实例,因此第一、三步骤可省略,而只需要做第2步即可。
在调用线程中完成:
(1)创建message,并填充内容。
(2)使用被调用类创建的Handler实例,调用sendMessage(Message msg)方法。

Handler 与线程的关系
Handler 一般运行于主线程内,也可以运行在子线程中,但是一定要创建Looper对象。主线程中Android已经为之创建了Looper对象

 

使用Handler的两种常见情况:
1、只能在主UI中修改UI。但实际上,有部分UI需要在子线程中控制其修改逻辑,因此子线程需要通过handler通知主线程修改UI。这在游戏开发中尤其常见,比如需要让新启动的线程周期性的改变UI。、

子线程通知主UI线程修改UI组件的例子,新线程周期性的修改ImageView所显示的图片:

这个例子是Handler在主线程中获取,处理消息,在子线程中发送消息

 

public class HandlerTest extends Activity
{
	// 定义周期性显示的图片的ID
	int[] imageIds = new int[]
	{
		R.drawable.java,
		R.drawable.ee,
		R.drawable.ajax,
		R.drawable.xml,
		R.drawable.classic
	};
	int currentImageId = 0;

	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		final ImageView show = (ImageView) findViewById(R.id.show);
		final Handler myHandler = new Handler()//在主线程中,获取,处理消息,更新UI组件,可以修改UI组件
		{
			@Override
			public void handleMessage(Message msg)
			{
				// 如果该消息是本程序所发送的
				if (msg.what == 0x1233)
				{
					// 动态地修改所显示的图片
					show.setImageResource(imageIds[currentImageId++
						% imageIds.length]);
				}
			}
		};
		// 定义一个计时器,让该计时器周期性地执行指定任务。子线程通知主线程修改UI组件,实现进程间通信
		new Timer().schedule(new TimerTask()
		{
			@Override
			public void run()
			{
				// 发送空消息
				myHandler.sendEmptyMessage(0x1233);在线程中发送消息
			}
		}, 0, 1200);
	}
}

2、为避免ANR,应该在子线程中执行耗时较长的操作,而此操作完成后,有可能需要通知主线程修改UI。

 

在子线程中执行耗时任务后,通知主线程修改UI组件的例子:使用新进程计算质数,并用Toast显示

这个例子是在主线程中发送消息,在子线程中获取,处理消息

 

public class CalPrime extends Activity
{
	static final String UPPER_NUM = "upper";
	EditText etNum;
	CalThread calThread;
	// 定义一个线程类
	class CalThread extends Thread
	{
		public Handler mHandler;

		public void run()
		{
			Looper.prepare();//创建Looper对象,每个线程使用Handler时都要有一个Looper对象
			mHandler = new Handler()//在子线程中用handler获取,处理消息
			{
				// 定义处理消息的方法
				@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();
					}
				}
			};
			Looper.loop();//启动Looper
		}
	}
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		etNum = (EditText)findViewById(R.id.etNum);
		calThread = new CalThread();
		// 启动新线程
		calThread.start();
	}
	// 为按钮的点击事件提供事件处理函数
	public void cal(View source)
	{
		// 创建消息
		Message msg = new Message();
		msg.what = 0x123;
		Bundle bundle = new Bundle();
		bundle.putInt(UPPER_NUM ,
			Integer.parseInt(etNum.getText().toString()));
		msg.setData(bundle);
		// 在主线程中向新线程中的Handler发送消息
		calThread.mHandler.sendMessage(msg);//在主线程中发送消息
	}
}</integer></integer>

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • Handler消息传递机制(二)Handler,Loop,Message,MessageQueue的工作原理
  • Handler消息传递机制(一)

相关文章

  • 2017-05-26多线程中使用curl致coredump问题
  • 2017-05-26自定义图片轮播,简单就是好用,自定义图片轮播
  • 2017-05-26和我一起看API(一)你所不知道的LinearLayout补充,apilinearlayout
  • 2017-05-26Android线程管理(三)&mdash;&mdash;Thread类的内部原理、休眠及唤醒,androidthread
  • 2017-05-26Solaris IPMP两种配置方法
  • 2017-05-26Android Scroll详解(一):基础知识
  • 2017-05-26Android Couldn&#39;t load BaiduMapSDK,androidbaidumapsdk
  • 2017-05-26微博API常用方法,博API常用方法
  • 2017-05-26Linux内核系列—12.b.操作系统开发之从Loader跳入保护模式,12.bloader
  • 2017-05-26Android之ContentProvider数据存储,contentprovider

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • Android开发:内存机制分析——堆和栈
    • okhttp3.4.1+retrofit2.1.0实现离线缓存,retrofitokhttp缓存
    • 2.3.5.RadioButton(单选按钮)&Checkbox(复选框)
    • Android-Universal-Image-Loader (图片异步加载缓存库)对Bitmap的优化处理
    • Android 反编译和混淆,android反编译混淆
    • 在Mac系统中 下载、安装AndroidStudio
    • Android App发布到应用市场的流程
    • Activity、View、Window三者之间的关系
    • [转]File Descriptor泄漏导致Crash: Too many open files,descriptorcrash
    • Kotlin的android扩展:对findViewById说再见(KAD 04),kotlinfindviewbyid

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有