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

来源:互联网 发布:北京大学大数据学院 编辑:程序博客网 时间:2024/04/29 00:05

我们知道出于性能优化的考虑,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() {@Overridepublic 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;}}};@Overrideprotected 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;@Overridepublic void run() {Log.i("run", "run");Looper.prepare();mHandler = new Handler() {@Overridepublic 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();}}@Overridepublic 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;}@Overridepublic 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