zoukankan      html  css  js  c++  java
  • 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>
  • 相关阅读:
    Ubuntu双系统
    Qt实现 动态化遍历二叉树(前中后层次遍历)
    Qt学习资料
    Qt学习--信号与槽(多窗口的实现)
    Qt 学习-----helloword
    二叉树的前中后层次遍历
    悬浮在网页右侧并可依次展开的菜单导航
    js实现仿华为手机计算器,兼容电脑和手机屏幕
    jquery json实现面向对象 百度十二星座
    knova绘制进度条
  • 原文地址:https://www.cnblogs.com/Eric-zhao/p/5240718.html
Copyright © 2011-2022 走看看