您的位置:首页 > 移动开发 > Android开发

对Android Handler Message Looper常见用法,知识点的一些总结

2015-03-06 09:12 597 查看
Android 非UI线程中是不能更新UI的,Handler是Android
提供的一套更新UI的机制,也是用来发送消息和处理消息的一套机制。
以前刚接触的Handler的时候,感觉总是很困惑,对Handler原理也是一知半解,现在对Handler常见用法,知识点总结一下。
先看一下谷歌Android官方文档对Handler的描述:


Class Overview

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.

它允许用户发送、处理消息和与线程的消息队列相关联的 runnable 对象。每一个 handler 实例都与一个单独的线程相关联。每次创建一个新的 hander 对象时,它都与创建该对象的线程或者该线程中的消息队列绑定在一起,这样handler 就可以发送消息和
runable 对象到消息队列中,并在从消息队列中取出的时候处理它们。


1. Handler的构造函数

Handler()
Default constructor associates this handler with the
Looper
for
the current thread.

Handler(Handler.Callback callback) Constructor
associates this handler with the
Looper
for
the current thread and takes a callback interface in which you can handle messages.

Handler(Looper looper)
Use the provided
Looper
instead
of the default one.

Handler(Looper looper, Handler.Callback callback)
Use the provided
Looper
instead
of the default one and take a callback interface in which to handle messages.

说明:
Handler()是最常用的一种


Handler(Handler.Callback callback)可以截获消息,

Handler(Looper looper)指定了Looper对象,在实际开发中常用HandlerThread.getLooper()。


2. 关于Message

Handler如果使用sendMessage的方式把消息入队到消息队列中,需要传递一个Message对象,而在Handler中,需要重
写handleMessage()方法,用于获取工作线程传递过来的消息。

发送消息常见的方式如下,用法大同小异。

sendEmptyMessage(int what) 发送一个空的消息
sendMessageAtTime(Message msg,
long uptimeMillis) 在某一时间点发送一个空的消息
sendMessageDelayed(Message msg,
long delayMillis) 延迟发送一个空的消息
sendMessage(Message
msg)发送消息,消息中可以携带参数

Message的参数:

int what:定义的消息码,一般用于设定消息的标志。
int arg1:简单参数
int arg2:[b]简单参数[/b]
Object obj:传递一个任意的对象。


移除Message

removeMessages(int what)
Remove any pending posts of messages

with code 'what' that are in the message queue.






3. 关于Post

Post 会传递一个Runnable对象到消息队列中

Post常见方法

post(Runnable
r) Causes the Runnable r to be added to the message queue.
postDelayed(Runnable
r, long delayMillis) Causes the Runnable r to be added to the message queue, to be run after the specified amount of time elapses.
postAtTime(Runnable
r,Object token, long uptimeMillis) Causes the Runnable r to be added to the message queue, to be run at a specific time given byuptimeMillis.



从消息队列中移除一个Runnable对象

removeCallbacks(Runnable r)Remove
any pending posts of Runnable r that are in the message queue.

[b][/b]

4. 关于MessageQueue

MessageQueue 是消息队列,在MainThread创建的时候会创建一个Looper,在创建Looper的时候,会创建MessageQueue();


5. 关于Looper

Looper.loop()是一个死循环,用来循环查询消息队列,并把消息回传给handler。


6. Demo说明



1.1 发送空消息和移除消息,这里以sendEmptyMessageDelayed()为例

public class Test1 extends Activity implements OnClickListener {

	private TextView tv;
	private Button btn;
	private int i = 0;

	Handler handler = new Handler() {
		public void handleMessage(Message msg) {
			tv.setText("Hello 改变了"+i++);
			handler.sendEmptyMessageDelayed(0, 1 * 1000); //延迟一秒发送

		};
	};

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

	}

	private void setView() {
		tv = (TextView) this.findViewById(R.id.tv);
		btn = (Button) this.findViewById(R.id.btn);
		btn.setOnClickListener(this);
	}

	private void test1() {

		new Thread() {
			public void run() {

				handler.sendEmptyMessageDelayed(0, 1 * 1000); //延迟一秒发送
			};
		}.start();
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {

		case R.id.btn:
			handler.removeMessages(0);//移除消息
			break;

		default:
			break;
		}

	}

}


效果图,数字每隔一秒,自增1,点击,数字会停止自增:



1.2
使用new Message(),并给Message赋值,使用handler.sendMessage(msg)发送


public class Test2 extends Activity implements OnClickListener {

	private TextView tv;

	Handler handler = new Handler() {
		public void handleMessage(Message msg) {
			
			tv.setText("msg.what=" + msg.what + ",     msg.arg1=" + msg.arg1
					+ ",    msg.arg2=" + msg.arg2 + ",    msg.obj=" + msg.obj);

		};
	};

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

	}

	private void setView() {
		tv = (TextView) this.findViewById(R.id.tv);

	}

	private void test() {

		new Thread() {
			public void run() {

				Message msg = new Message();
				UserBean userBean = new UserBean();
				userBean.setName("Jim");
				userBean.setPwd("123456");
				msg.what = 1;
				msg.arg1 = 2;
				msg.arg2 = 3;
				msg.obj = userBean;
				handler.sendMessage(msg);
			};
		}.start();
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
//
//		case R.id.btn:
//			handler.removeMessages(0);//移除消息
//			break;

		default:
			break;
		}

	}

}

实体类

public class UserBean {

	public String name;
	
	public String pwd;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPwd() {
		return pwd;
	}

	public void setPwd(String pwd) {
		this.pwd = pwd;
	}

	@Override
	public String toString() {
		return "UserBean [name=" + name + ", pwd=" + pwd + "]";
	}
	
	
}


效果图如下,可以看到消息成功传递和接收。



1.3
使用obtainMessage()获取已绑定的消息,并给Message赋值,使用msg.sendToTarget()发送


public class Test3 extends Activity implements OnClickListener {

	private TextView tv;

	Handler handler = new Handler() {
		public void handleMessage(Message msg) {

			tv.setText("msg.what=" + msg.what + ",     msg.arg1=" + msg.arg1
					+ ",    msg.arg2=" + msg.arg2 + ",    msg.obj=" + msg.obj);

		};
	};

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

	}

	private void setView() {
		tv = (TextView) this.findViewById(R.id.tv);

	}

	private void test() {

		new Thread() {
			public void run() {

				// Message msg = new Message();
				Message msg = handler.obtainMessage();
				UserBean userBean = new UserBean();
				userBean.setName("Jim");
				userBean.setPwd("123456");
				msg.what = 1;
				msg.arg1 = 2;
				msg.arg2 = 3;
				msg.obj = userBean;
				// handler.sendMessage(msg);n
				msg.sendToTarget();
			};
		}.start();
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		//
		// case R.id.btn:
		// handler.removeMessages(0);//移除消息
		// break;

		default:
			break;
		}

	}

}


效果和上图一样

2 Post 会传递一个Runnable对象到消息队列中

2.1
使用Post方式传递一个Runnable对象到消息队列和移除


public class Test4 extends Activity implements OnClickListener {

	private TextView tv;
	private Button btn;
	private int i = 0;

	Handler handlerPost = new Handler();
	// 线程中运行该接口的run函数
	Runnable update_thread = new Runnable() {
		public void run() {
			// System.out.println("activity_id---->"+Thread.currentThread().getId());
			// System.out.println("activity_name---->"+Thread.currentThread().getName());
			tv.setText("handlerPost:"+i++);
			// 延时1s后又将线程加入到线程队列中
			handlerPost.postDelayed(update_thread, 1000);

		}
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.test4);
		setView();
		System.out
				.println("activity_id0---->" + Thread.currentThread().getId());
		System.out.println("activity_name0---->"
				+ Thread.currentThread().getName());
		test();

	}

	private void setView() {
		tv = (TextView) this.findViewById(R.id.tv);
		btn = (Button) this.findViewById(R.id.btn);
		btn.setOnClickListener(this);
	}

	private void test() {

		// 将线程接口立刻送到线程队列中
		handlerPost.post(update_thread); // handler使用了post方法启动了runnbale,其实启动的线程和activity主线程是同一个线程
		// Thread t = new Thread(update_thread);
		// //这样绑定的线程与它所在的activity线程就不是同一个线程了
		// t.start();
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {

		case R.id.btn:
			handlerPost.removeCallbacks(update_thread);// 将接口从线程队列中移除
			break;

		default:
			break;
		}

	}

}

说明:

handler使用了post方法启动了runnbale,其实启动的线程和activity主线程是同一个线程

如果使用

Thread
t = new Thread(update_thread);

t.start();

这样绑定的线程与它所在的activity线程就不是同一个线程了

效果图:



3 Handler(Looper
looper)的使用,使用handThread.getLooper()作为参数。


注意:如果
thread.getLooper()中的thread为子线程,则会报空指针异常,因为当主线程执行Handler(Looper
looper)

的时候,子线程的Looper对象还未创立。



public class Test5 extends Activity implements OnClickListener {

	private TextView tv;
	HandlerThread handThread;
	Handler handler;

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

	}

	private void setView() {
		tv = (TextView) this.findViewById(R.id.tv);

	}

	private void test() {
		
		// HandlerThread
		handThread = new HandlerThread("handThread");
		handThread.start();
		handler = new Handler(handThread.getLooper()) {
			public void handleMessage(Message msg) {

				tv.setText("HandlerThread");

			};
		};
		handler.sendEmptyMessage(0);
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		//
		// case R.id.btn:
		// handler.removeMessages(0);//移除消息
		// break;

		default:
			break;
		}

	}

}


效果图:



Demo下载地址:http://download.csdn.net/detail/yalinfendou/8477587
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: