鸟语天空
Handler和消息队列
post by:追风剑情 2015-6-14 15:26

    防止阻塞UI线程的一个好方法是让任务线程在后台运行。然而,当任务完成时,你常常需要更新UI。对于UI的更新只能由UI线程执行,否则将会产生异常。可以使用Handler类来做到这一点。Handler允许你发送在一段时间之后再由其处理的消息。这些消息可以立即进行处理,也可以计划好在将来的某段时间进行处理。Handler在handleMessage方法中处理消息。

    默认情况下,一个Handler实例是绑定在创建它的线程上的(通常是主线程)。绑定Handler到UI线程上为异步更新UI提供了一个方便的方法。然而,你同样可以选择提供一个可选的Looper实例,让Handler运行在单独的线程上。循环类用于为一个线程运行消息循环。通过使用循环类,你可以发送消息并让它们运行于任何线程实例上。

注意:Looper类创建和管理一个包含单个线程的所有消息的MessageQueue对象。UI线程已经为你创建了一个消息队列和循环类。

Handler具有发送在一段时间之后再进行处理的消息的能力,这一点使得它非常适合实现基于时间的行为。

仅仅为了从一个后台线程中更新UI而创建一个Handler的情况很常见。Android提供了Activity.runOnUIThread方法,为这种情况提供了一条捷径。这个方法采用一个runnable并将其发送给UI线程的处理消息的Handler。主线程会在空闲时运行在runnable中的代码。

计时器实例

package com.example.testhandler;

import android.support.v7.app.ActionBarActivity;
import android.text.format.DateUtils;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;

public class MainActivity extends ActionBarActivity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		startTimer();//启动计时器
	}
	
	//========================= 以下为计时器代码  =======================
	long mStart = 0;
	long mTime = 0;
	private Handler mHandler = new Handler() {
		//Handler回调函数将会默认在UI线程上执行,除非你明确地给出它会运行于另一个线程上。
		public void handleMessage(Message msg) {
			
			long current = System.currentTimeMillis();
			mTime += current - mStart;
			mStart = current;
			TextView counter = (TextView) MainActivity.this.findViewById(R.id.cdText);
			counter.setText(DateUtils.formatElapsedTime(mTime/1000));
			mHandler.sendEmptyMessageDelayed(0, 250);
		}
	};
	
	//启动
	private void startTimer() {
		mStart = System.currentTimeMillis();
		//为了阻止开启定时器两次,在发送下一条消息时移除任何存在的消息。
		mHandler.removeMessages(0);
		mHandler.sendEmptyMessage(0);
	}
	
	//停止
	private void stopTimer() {
		mHandler.removeMessages(0);
	}
	
	//重置
	private void resetTimer() {
		stopTimer();
		mTime = 0;
	}
	
	//检测定时器是否已经被停止
	private boolean isTimerRunning() {
		return mHandler.hasMessages(0);
	}
}



运行结果

TestHandler.png

评论:
发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容