Android的消息处理机制,handler,message,looper(一)

  当应用程序启动时,Android首先会开启一个主线程(也就是UI线程),主线程为管理界面中的UI控件。在程序开发时,对于比较耗时的操作,通常会为其开辟一个单独的线程来执行,以尽可能减少用户的等待时间。在Android中,默认情况下,所有的操作都是在主线程中进行的,主线程负责与UI相关的事件。而在自己新建的线程中,不能对UI进行操作。因此Android提供了消息处理传递机制来解决这一问题。

一、几个概念:

  Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。Message是线程之间传递信息的载体,包含了对消息的描述和任意的数据对象。Message中包含了两个额外的 int字段和一个object字段,这样在大部分情况下,使用者就不需要再做内存分配工作了。虽然Message的构造函数是public的,但是最好是使用Message.obtain( )或Handler.obtainMessage( )函数来获取Message对象,因为Message的实现中包含了回收再利用的机制,可以提供效率。

  MessageQueue:简单的说就是用来存放Message,但是Message是由Looper来分发的,Message不能直接添加到MessageQueue中,而是要通过与Looper关联的Handler去添加。其中的Message是由Looper来分发的,Message不能直接添加到MessageQueue中,而是要通过与Looper关联的Handler去添加。

  Looper:用来循环读取存放于MessageQueue中的消息。一个线程对应一个Looper,一个Looper对象对应一个MessageQueue。Android中新增的线程是没有开启消息循环的,需要在线程中调用perpare函数,然后调用loop去处理消息。主线程除外。系统自动为主线程创建Looper对象。

  Handler:实现消息的发送以及处理,负责发送用户消息以及调用用户注册的callback或接口进行消息处理。因此每个消息肯定有一个对应的handler,否则消息无法被发送/处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。

二、消息机制的原理:

  现Message机制需要Handler、Message、Looper三个之间的互相作用来实现;当线程A需要发消息给线程B的时候,线程B要用自己的Looper实例化Handler类,就是构造handler对象时,把当前线程的Looper传给Handler构造函数,handler本身会保存对Looper的引用,handler构造好以后,就可以用handler的obtainMessage方法实例化Message对象,只要把要传的数据给Handler,Handler就会构造Message对象,并且把Message对象添加到消息队列里面。然后就可以调用handler的sendMessage方法把Message对象发送出去,Looper就把消息放到消息队列中;最后当Looper知道消息队列不为空时候,就会循环的从消息队列中取消息,取出消息就会调用刚才实例化好的Handler对象的handleMessage方法取处理消息,整个Message过程就是这样。

三、第一个例子:

UI上两个button,点击不同button的时候显示不同的文本:

MainActivity.java
 1 package com.zdx.messagetest;
 2 
 3 import java.security.spec.MGF1ParameterSpec;
 4 
 5 import android.app.Activity;
 6 import android.os.Bundle;
 7 import android.os.Handler;
 8 import android.os.Looper;
 9 import android.os.Message;
10 import android.util.Log;
11 import android.view.Menu;
12 import android.view.MenuItem;
13 import android.view.View;
14 import android.widget.Button;
15 import android.widget.TextView;
16 
17 public class MainActivity extends Activity {
18     public boolean clickIF,threadBoolean=false;
19     private Button  bt_success,bt_failed;
20     private TextView tv_textShow;
21 
22     @Override
23     protected void onCreate(Bundle savedInstanceState) {
24         super.onCreate(savedInstanceState);
25         setContentView(R.layout.activity_main);
26         tv_textShow = (TextView) findViewById(R.id.tv_show);
27     }
28     public void showSuccess(View v){
29         threadBoolean=false;
30         clickIF=true;
31         Log.i("zdx", "clickIF为true");
32         LoThread loThread = new LoThread();
33         Thread mThread = new Thread(loThread);
34         mThread.start();
35         
36         
37     }
38     public void showFailed(View v){
39         threadBoolean=false;
40         clickIF=false;
41         Log.i("zdx", "clickIF为false");
42         LoThread loThread = new LoThread();
43         Thread mThread = new Thread(loThread);
44         mThread.start();
45         
46     }
47     
48     private Handler mHandler = new Handler(){
49 
50         @Override
51         public void handleMessage(Message msg) {
52             // TODO Auto-generated method stub
53             super.handleMessage(msg);
54             switch(msg.what){
55             case 0:
56                 tv_textShow.setText(String.valueOf(msg.obj));
57                 threadBoolean=true;
58                 break;
59             case 1:
60                 tv_textShow.setText(String.valueOf(msg.obj));    
61                 threadBoolean=true;
62                 break;
63             }            
64         }                
65     };
66     private class LoThread implements Runnable{
67 
68         @Override
69         public void run() {
70             // TODO Auto-generated method stub
71             while(!threadBoolean){                
72                 Looper.prepare();
73                 if(clickIF)
74                 {
75                     String successful = "成功";
76                     Message messages = mHandler.obtainMessage(0, successful);
77                     messages.sendToTarget();
78                     Log.i("zdx", "成功");
79                 }
80                 else
81                 {
82                     String failure = "失败";
83                     Message messages = mHandler.obtainMessage(1, failure);
84                     messages.sendToTarget();
85                     Log.i("zdx", "失败");
86                 }
87                 if (threadBoolean) {
88                     Thread.currentThread().interrupt();
89                 }
90                 Looper.loop();
91             }
92         }
93     }
94 }

activity_main.xml

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:paddingBottom="@dimen/activity_vertical_margin"
 6     android:paddingLeft="@dimen/activity_horizontal_margin"
 7     android:paddingRight="@dimen/activity_horizontal_margin"
 8     android:paddingTop="@dimen/activity_vertical_margin"
 9     tools:context="com.zdx.messagetest.MainActivity" >
10 
11     <LinearLayout
12         android:id="@+id/linearLayout1"
13         android:layout_width="wrap_content"
14         android:layout_height="wrap_content"
15         android:orientation="horizontal" >
16 
17         <Button
18             android:id="@+id/bt_success"
19             android:layout_width="wrap_content"
20             android:layout_height="wrap_content"
21             android:layout_alignParentLeft="true"
22             android:layout_alignParentTop="true"
23             android:text="@string/s_successful" 
24             android:onClick="showSuccess"/>
25 
26         <Button
27             android:id="@+id/bt_failed"
28             android:layout_width="wrap_content"
29             android:layout_height="wrap_content"
30             android:layout_centerHorizontal="true"
31             android:text="@string/s_failure" 
32             android:onClick="showFailed"/>
33     </LinearLayout>
34 
35     <TextView
36         android:id="@+id/tv_show"
37         android:layout_width="match_parent"
38         android:layout_height="60dp"
39         android:layout_alignParentLeft="true"
40         android:layout_below="@+id/linearLayout1"
41         android:layout_marginTop="17dp"/>
42 
43 </RelativeLayout>

 

posted @ 2016-03-04 02:38  弘文馆校书  阅读(320)  评论(0编辑  收藏  举报