Android消息处理机制(Looper,Handler,MessageQueue笔记)

来源:互联网 发布:三三复制系统源码 编辑:程序博客网 时间:2024/06/06 02:39

定义:

Message:消息,包含ID,消息处理对象及消息数据,由MessageQueue统一管理,最总由Handler处理

Handler:消息处理者,负责Message的发送及处理

MessageQueue:消息对象,用来存放Handler发送过来的消息,按FIFO顺序。

Looper:消息循环者,不断地从MessageQueue中抽取Message执行。因此,一个MessageQueue需要一个Looper

三者关系如下:


上图详细说明了消息处理的整个流程。


以下使用handler消息机制时的几个要点:

1.handler可以在任意线程发送消息(UI主线程或者工作线程),这些消息会被添加到关联的MQ上。

2.handler是在它关联的looper线程中处理消息的。

android 主线程也是一个Looper线程,所以普通的做法就是在主线程中new handler对象出来,然后使用这个hanlder来发送和处理消息,并直接可以在当前的主线程中更新UI界面。

所以利用handler一个常用的解决方案是Activity中创建handler,并将引用传递给worker thread(工作线程),工作线程执行完异步任务后使用handler发送消息,通知UI更新界面。


下面一个简单的例子:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >     <TextView        android:id="@+id/handler"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="handler message " /></LinearLayout>

/** * Copyright (C) 2012 HongCheng System Inc. */package com.android.handler;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.widget.TextView;/** * @author yangjp * @version V1.0 */public class HandlerActivity extends Activity {private TextView textView = null;private Handler handler = null;/* * (non Javadoc)<p>Title: onCreate</p><p>Description: </p> *  * @param savedInstanceState *  * @see android.app.Activity#onCreate(android.os.Bundle) */@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.handler);textView = (TextView)findViewById(R.id.handler);handler = new MyHandler(textView);Thread thread = new WorkerThread(handler);thread.start();}/** * 工作线程 *@authoryangjp *@versionV1.0 */private class WorkerThread extends Thread{        private Handler handler = null;                public WorkerThread(Handler handler){        this.handler = handler;        }public void run() {        try {Thread.sleep(1000 * 5);// 暂停5秒Message message = handler.obtainMessage();message.what = 1;message.arg1 = 100;handler.sendMessage(message);} catch (InterruptedException e) {e.printStackTrace();}}}/** * 消息处理者 *@authoryangjp *@versionV1.0 */private class MyHandler extends Handler{private TextView textView = null;public MyHandler(TextView textView){this.textView = textView;}/*(non Javadoc)  *<p>Title: handleMessage</p>  *<p>Description: </p>  *@param msg  *@see android.os.Handler#handleMessage(android.os.Message)  */@Overridepublic void handleMessage(Message msg) {// 处理消息,更新UI界面switch(msg.what){case 1:String result = "执行结果进度:" +  msg.arg1;textView.setText(result);break;}}}}
 

在主线程(UI线程)里,如果创建Handler时不传入Looper对象,那么将直接使用主线程(UI线程)的Looper对象(系统已经帮我们创建了);在其它线程里,如果创建Handler时不传入Looper对象,那么,这个Handler将不能接收处理消息。在这种情况下,通用的作法是:


  class LooperThread extends Thread {                               public Handler mHandler;                               public void run() {                                               Looper.prepare();                                               mHandler = new Handler() {                                                               public void handleMessage(Message msg) {                                                                              // process incoming messages here                                                               }                                               };                                               Looper.loop();                               }                }

在创建Handler之前,为该线程准备好一个LooperLooper.prepare),然后让这个Looper跑起来(Looper.loop),抽取Message,这样,Handler才能正常工作。

因此,Handler处理消息总是在创建Handler的线程里运行。而我们的消息处理中,不乏更新UI的操作,不正确的线程直接更新UI将引发异常。因此,需要时刻关心Handler在哪个线程里创建的。


1.Activity.runOnUiThread(Runnable)

2.View.post(Runnable)

3.View.postDelayed(Runnable, long)

4.Handler

注意:在post(Runnable action)方法里View获得当前线程UI线程Handler然后将action对象postHandler里。在Handler里,它将传递过来的action对象包装成一个MessageMessagecallbackaction),然后将其投入UI线程的消息循环中。在Handler再次处理该Message时,有一条分支(未解释的那条)就是为它所设,直接调用runnablerun方法。而此时,已经路由到UI线程里,因此,我们可以毫无顾虑的来更新UI

不确定当前线程时,更新UI时尽量调用post方法






0 0
原创粉丝点击