Handler机制详述1---Handler的简介和用法

1.Handler简介

handler是Android系统封装的用于线程更新UI,消息处理的机制。

[说明]

查看Android Framework源码可以看到,常见的Activity的生命周期onCreate(), onStart(), onResume(), onPause(), onStop(), onDestroy()都是通过handler发送不同Message,AMS(Activity Manager Service)通过Handler向ActivityThread发送消息,在ActivityThread中执行不同的Activity的周期。

2.Handler的用法

// Google文档的地址
http://developer.android.com/reference/android/os/Handler.html
// Google对Handler的介绍
A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue.
Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler,
it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver
messages and runnables to that message queue and execute them as they come out of the message queue.

[说明]

查看Google文档可以看出,Handler允许我们绑定(associate with)一个线程的MessageQueue,并通过该handler向该线程发送Message或者Runnable对象,一个Handler绑定了一个线程以及这个线程的MessageQueue,当你创建一个Handler的时候,该Handler就会和Thread以及该Thread的MessageQueue绑定。

首先,下面的程序,在子线程中更新UI:

public class MainActivity extends Activity
{

	TextView tv;

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		tv = (TextView) findViewById(R.id.tv);

		new Thread()
		{
			public void run()
			{
				try
				{
					Thread.sleep(1000);
				} catch (InterruptedException e)
				{
					e.printStackTrace();
				}
				tv.setText("update UI");
			};
		}.start();
	}

}

运行之后,程序奔溃,logcat中打印信息:

[说明]

上面信息的主要内容是,不允许在子线程中更新UI线程,Android自身设定的机制则是只能在子线程中处理耗时的操作,处理完毕之后,在UIThread中更新UI,而子线程是不能更新UI的。

Handler主要提供了下面API来实现子线程与UIThread之间的通信问题:

  • sendMessage
  • sendMessageDelayed
  • post(Runnable)
  • postDelayed(Runnable, long)

(1). 使用sendMessage进行线程通信:

public class MainActivity extends Activity
{

	@SuppressLint("HandlerLeak")
	Handler handler = new Handler()
	{
		public void handleMessage(android.os.Message msg)
		{
			if (msg.what == 0x1)
			{
				tv.setText("update UI");
			}
		};
	};

	TextView tv;

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		tv = (TextView) findViewById(R.id.tv);

		new Thread()
		{
			public void run()
			{
				try
				{
					Thread.sleep(1000);
				} catch (InterruptedException e)
				{
					e.printStackTrace();
				}
				handler.sendEmptyMessage(0x1);
			};
		}.start();
	}

}

sendMessageDelayed(Message, long)是延迟long毫秒之后,再发送Message。

(2).post(Runnable)

public class MainActivity extends Activity
{

	@SuppressLint("HandlerLeak")
	Handler handler = new Handler()
	{
		public void handleMessage(android.os.Message msg)
		{
		};
	};

	TextView tv;

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		tv = (TextView) findViewById(R.id.tv);

		new Thread()
		{
			public void run()
			{
				try
				{
					Thread.sleep(1000);
				} catch (InterruptedException e)
				{
					e.printStackTrace();
				}

				handler.post(new Runnable()
				{

					@Override
					public void run()
					{
						tv.setText("update UI");
					}
				});
			};
		}.start();
	}

}

下面利用Handler实现一个简单的图片轮换的功能,每隔1s循环替换ImageView显示的图片:

public class MainActivity extends Activity
{

	Handler handler = new Handler();

	ImageView img;
	int[] images = // 存放循环播放的图片
	{ R.drawable.weather_0, R.drawable.weather_1, R.drawable.weather_2, R.drawable.weather_3, R.drawable.weather_4 };
	private int imgCount = images.length;
	private int index = 0;
	private long delayMillis = 1000L; // 每隔1s循环一次

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		img = (ImageView) findViewById(R.id.img);
		handler.post(imgRunnable);
	}

	private Runnable imgRunnable = new Runnable()
	{
		public void run()
		{
			img.setBackgroundResource(images[index % imgCount]);
			index++;
			handler.postDelayed(imgRunnable, delayMillis);
		}
	};

}

对应的xml文件中只有一个<ImageView />:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ImageView
        android:id="@+id/img"
        android:layout_width="200.0dip"
        android:layout_height="200.0dip"
        android:layout_centerInParent="true"
        android:contentDescription="@string/app_name" />

</RelativeLayout>

[注意]若要终止上面的循环,可以使用下面的方法:

handler.removeCallbacks(imgRunnable);

下面使用Handler演示消息截获的用法:

[说明]

Handler的创建有一个接受一个Handler.Callback参数的构造方法,此方法内部的handlerMessage(Message msg)方法有boolean类型的返回值,return true可以实现类似消息截获的效果:

public class SecondActivity extends Activity
{

	@SuppressLint("HandlerLeak")
	Handler handler = new Handler(new Handler.Callback()
	{
		@Override
		public boolean handleMessage(Message msg)
		{
			if (msg.what == 0x1)
			{
				Log.v(LOG, "返回true,消息被截获");
				return true;
			} else if (msg.what == 0x2)
			{
				Log.v(LOG, "返回false,不截获");
				return false;
			}
			return false;
		}
	})
	{
		@Override
		public void handleMessage(Message msg)
		{
			Log.v(LOG, "收到消息....");
		}
	};

	Button btn1, btn2;
	private final String LOG = "SecondActivity";

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_second);

		btn1 = (Button) findViewById(R.id.btn1);
		btn1.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
				handler.sendEmptyMessage(0x1);
			}
		});

		btn2 = (Button) findViewById(R.id.btn2);
		btn2.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
				handler.sendEmptyMessage(0x2);
			}
		});
	}
}

界面效果如下:

点击“消息截获”按键,会向handler对象传递0x1的Message,在Handler.Callback的boolean handlerMessage()方法中返回true,此时该Message不会再被void handlerMessage()方法接收到:

相反,当点击“消息不截获”按键,会发送0x2消息,Handler.Callback的boolean handlerMessage()返回false,此时消息仍然会被void handlerMessage()方法所获的:

查看Handler的源码可以看到,消息的传递是通过dispatchMessage(Message msg)来发送的,而dispatchMessage函数如下:

当使用了Handler包含Handler.Callback参数的构造函数时,mCallback != null,此时会执行mCallback.handlerMessage(msg)方法,若此方法返回true,则直接执行return返回,不再执行下面的handlerMessage(msg),若mCallback.handlerMessage(msg)返回false,mCallback.handlerMessage(msg)方法被调用之后,还会继续调用handlerMessage(msg)方法。

时间: 2024-10-06 23:29:24

Handler机制详述1---Handler的简介和用法的相关文章

Handler机制详述2---Looper,MessageQueue

1. 为什么Android会设计Handler去更新UI Handler根本上是为了解决多线程之间引发的并发问题,在ActivityThread中,要是有多个子线程在没有加锁的情况下更新UI,有可能引发UI显示错乱的现象,但要是对更新UI的操作进行类似synchronized加锁机制的话,会造成性能下降,而Handler允许多线程向一个MessageQueue中押入Message,在UIThread中通过轮询的方式取出Message,并进行对应的处理,这样就可以避免UI显示错乱的问题,又不会降低

为什么要有handler机制

在Android的UI开发中,我们经常会使用Handler来控制主UI程序的界面变化.有关Handler的作用,我们总结为:与其他线程协同工作,接收其他线程的消息并通过接收到的消息更新主UI线程的内容. 我们假设在一个UI界面上面,有一个按钮,当点击这个按钮的时候,会进行网络连接,并把网络上的一个字符串拿下来显示到界面上的一个 TextView上面,这时就出现了一个问题,如果这个网络连接的延迟过大,可能是10秒钟甚至更长,那我们的界面将处于一直假死状态,而如果这段时间超 过5秒钟的话,程序会出现

转:为什么要有handler机制?

在Android的UI开发中,我们经常会使用Handler来控制主UI程序的界面变化.有关Handler的作用,我们总结为:与其他线程协同工作,接收其他线程的消息并通过接收到的消息更新主UI线程的内容. 我们假设在一个UI界面上面,有一个按钮,当点击这个按钮的时候,会进行网络连接,并把网络上的一个字符串拿下来显示到界面上的一个 TextView 上面,这时就出现了一个问题,如果这个网络连接的延迟过大,可能是10秒钟甚至更长,那我们的界面将处于一直假死状态,而如果这段时间超 过5秒钟的话, 程序会

为什么要有handler机制?handler机制的原理

为什么要有handler机制? 在Android的UI开发中,我们经常会使用Handler来控制主UI程序的界面变化.有关Handler的作用,我们总结为:与其他线程协同工作,接收其他线程的消息并通过接收到的消息更新主UI线程的内容. 我们假设在一个UI界面上面,有一个按钮,当点击这个按钮的时候,会进行网络连接,并把网络上的一个字符串拿下来显示到界面上的一个 TextView上面,这时就出现了一个问题,如果这个网络连接的延迟过大,可能是10秒钟甚至更长,那我们的界面将处于一直假死状态,而如果这段

带你深入理解Android Handler机制

带你深入理解Android Handler机制 欢迎转载请注明来源 说到消息机制,我们一定会想到Handler,由于Android系统规定主线程不能阻塞超过5s,否则会出现"Application Not Responding".也就是说,你不能在主线程中进行耗时操作(网络请求,数据库操作等),只能在子线程中进行.下面先来看一下在子线程中访问UI会出现什么情况. public void click(View v){ new Thread(new Runnable() { @Overri

Handler机制源码分析

Handler机制 概念: handler机制是一种异步通信机制,通常用于子线程中数据更新后,通知主线程UI更新. handler运行框架图 从上面handler的运行框架图来看,为了完成handler整个流程,你必须按事先创建好四个东西: handler.Message.MessageQueue和Looper,也许Looper从上图来看并不是必须的,因为遍历MessageQueue只是调用了一个静态方法而已,并没有实例化一个Looper对象,既然这么想,那我们看看Looper.Loop()源码

Android Handler机制简介

1,Handler 的概念Handler 是用来干什么的?1)执行计划任务,可以在预定的时间执行某些任务,可以模拟定时器 2)线程间通信.在Android的应用启动时,会创建一个主线程,主线程会创建一个消息队列来处理各种消息.当你创建子线程时,你可以在你的子线程中拿到父线程中创建的Handler 对象,就可以通过该对象向父线程的消息队列发送消息了.由于Android要求在UI线程中更新界面,因此,可以通过该方法在其它线程中更新界面. 角色描述:1) Looper: 一个线程可以产生一个Loope

Android源码学习-----Handler机制

Handler 1.为什么要使用Handler 在Android4.0之后,google公司为从系统使用及用户体验方面考虑,如果做一些比较耗时的操作,就不允许直接在主线程中进行,而是要通过handler发送Message对象的方法来修改主线程的UI界面 2.Handler原理简介 在所有的UI操作界面中,都在执行一个死循环(Looper)在不断接收和监听用户发出的指令,一但接受到指令,就立即执行.   当子线程需要修改UI界面时,调用Handler的sendMessage()方法,向主线程发送消

handler机制原理分析(适合初学者)1.0

任何一个APK都是从framework层的ActivityThread的main()函数中开始执行,接着调用prepareMainLooer()为UI线程创建一个消息队列MessageQueue.并执行Looper.loop(). Handler消息机制的原理是什么了?我们先来写一个程序看看. 首先看new Handler().做了什么 可以看出在new Handler()中获取了Loop,messagequeue,callback,等对象. 接下来看handler.sendEmptyMessa