Android消息处理机制(Handler、Looper、MessageQueue与Message)

我们知道出于性能优化的考虑,Android的UI操作并不是线程安全的,这意味着多个线程并发操作UI组件,可能会导致线程安全的问题。因此,Android指定一条简单的规则,只允许UI线程操作Activity里面的UI组件。但是在实际的开发中,我们难免需要让新启动的线程周期性的改变界面组件的属性值,这就是需要Handler消息传递机制来实现。

Handle类的主要作用有两个:

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

2、在主线程中获取、处理消息。

为了让主线程能“适时”地处理新启动的线程所发送的消息,显然只能通过回调的方式来实现——开发者只要重写Handler类中处理消息的方法,当新启动的线程发送消息时,Handler类中处理消息的方法被自动回调。消息会发送到与之关联的MessageQueue,而Handler不断从MessageQueue中获取并处理消息——这将导致Handler类中的处理消息的方法被回调。

 

Handler中包含如下方法用于发送和处理消息。

voidhandleMessage(Message msg):处理消息的方法。该方法通常用于被重写。

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

final booleanhasMessage(int what,Object object):检查消息队列中是否包含what属性为指定值且object属性为指定对象的消息。

多个重载的Message(int what):获取消息。

sendEmptyMessage(intwhat):发送空消息。

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

final booleansendMessage(Message msg):立即发送消息。

通过这些方法,程序就可以方便的利用Handler来进行消息传递了。

 

Android是消息驱动的,实现消息驱动有几个要素:

    消息的表示:MessageHandler接收和处理的消息对象

    消息队列:MessageQueue消息队列,他是采用先进先出的方式来进行管理Message。程序创建Looper对象时,会在他的构造其中创建MessageQueue对象,

消息循环,用于循环取出消息进行处理:Looper每个线程只能拥有一个Looper对象。他的Looper方法负责读取MessageQueue中的消息。读到信息之后就把消息交给发送该消息的Handler进行处理。

所以MessageQueue是由Looper对象负责管理的,也就是说希望Handler正常工作,在当前的线程中必须有一个Looper对象。为了保证当前线程中有一个Looper对象可以分为以下两种情况考虑:

1、主UI线程线程中,系统已经初始化了一个Looper对象,因此程序直接创建Handler即可,然后就可以通过Handler发送和处理消息。

2、程序员主动启动的子线程,这个程序员必须自己创建一个Looper对象,并且启动他。创建Looper对象调用他的prepare()方法即可。

消息处理,消息循环从消息队列中取出消息后要对消息进行处理:HandlerHandler的作用有两个——发送和处理消息。程序使用Handler发送消息。被Handler发送的消息必须被送到指定的MessageQueue。接收消息是指Handler接收Loop处理完之后发送给他的消息。

看一下,下面的图片一定程度上解释了Android的消息处理机制。



下面我们来看一段代码。很好的解释了Handler和Looper的使用:

public class MainActivity extends Activity implements OnClickListener {
	private static final String UPPER_NUM = "upper_num";
	private static final String RESULTE_NUM = "result_num";
	protected static final int RESULTE = 0;
	EditText getEditText;
	Button calButton;
	TextView resultTextView;
	CalThread calThread;

	Handler mainHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case RESULTE:
				String result = msg.getData().getString(RESULTE_NUM);
				Log.i("mainHandler", "result=="+result);
				resultTextView.setText(result);
				break;
			default:
				break;
			}
		}

	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		calThread = new CalThread();
		// 启动新线程
		calThread.start();
		initView();
		callBackListener();
	}

	private void initView() {
		getEditText = (EditText) findViewById(R.id.editText1);
		calButton = (Button) findViewById(R.id.button1);
		resultTextView = (TextView) findViewById(R.id.textView3);
	}

	private void callBackListener() {
		calButton.setOnClickListener(this);
	}

	/**
	 * <功能描述>质数计算子线程
	 */
	class CalThread extends Thread {
		private Handler mHandler;

		@Override
		public void run() {
			Log.i("run", "run");
			Looper.prepare();
			mHandler = new 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开始计算所有的质数
						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.makeText(MainActivity.this, nums.toString(), Toast.LENGTH_LONG).show();
						Message msgMessage = new Message();
						msgMessage.what = RESULTE;
						Bundle bundle = new Bundle();
						bundle.putString(RESULTE_NUM, nums.toString());
						msgMessage.setData(bundle);
						// 向主线程中的Handler中发送消息
						mainHandler.sendMessage(msgMessage);
					}
				}

			};
			Looper.loop();
		}

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.activity_main, menu);
		return true;
	}

	@Override
	public void onClick(View v) {
		Log.d("Click", "Click");
		cal();

	}

	private void cal() {
		Message msgMessage = new Message();
		msgMessage.what = 0x123;
		Bundle bundle = new Bundle();
		bundle.putInt(UPPER_NUM, Integer.parseInt(getEditText.getText().toString()));
		msgMessage.setData(bundle);
		// 向新线程中的Handler中发送消息
		calThread.mHandler.sendMessage(msgMessage);
	}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值