• Android Handler Message多线程实例


    什么是Handler 

    handler通俗一点讲就是用来在各个进程之间发送数据的处理对象。在任何进程中,只要获得了另一个进程的handler则可以通过 handler.sendMessage(message)方法向那个进程发送数据。基于这个机制,我们在处理多线程的时候可以新建一个thread,这 个thread拥有UI线程中的一个handler。当thread处理完一些耗时的操作后通过传递过来的handler像ui线程发送数据,由UI线程 去更新界面。

      Handler类简介

    在Android平台中,新启动的线程是无法访问Activity里的Widget的,当然也不能将运行状态外送出来,这就需要有Handler机 制进行消息的传递了,Handler类位于android.os包下,主要的功能是完成Activity的Widget与应用程序中线程之间的交互。接下 来对该类中常用的方法进行介绍,如下表所示。

     Handler类的常用方法

    方法签名

         

    public void handleMessage (Message msg)

    子类对象通过该方法接收信息

    public final boolean sendEmptyMessage (int what)

    发送一个只含有 what 值的消息

    public final boolean sendMessage (Message msg)

    发送消息到 Handler 

    通过 handleMessage 方法接收

    public final boolean hasMessages (int what)

    监测消息队列中是否还

     what 值的消息

    public final boolean post (Runnable r)

    将一个线程添加到消息队列

     

    开发带有Handler类的程序步骤如下。

    在Activity或Activity的Widget中开发Handler类的对象,并重写handleMessage方法。

    在新启动的线程中调用sendEmptyMessage或者sendMe ssage方法向Handler发送消息。

    Handler类的对象用handleMessage方法接收消息,然后根据消息的不同执行不同的操作。

        在Android 中Handler和Message、Thread有着很密切的关系。Handler 主要是负责Message的分发和处理。但是这个Message从哪里来的呢?Message 由一个消息队列进行管理,而消息队列却由一个Looper进行管理。Android系统中Looper负责管理线程的消息队列和消息循环,具体实现请参考Looper的源码。 可以通过Loop.myLooper()得到当前线程的Looper对象,通过Loop.getMainLooper()可以获得当前进程的主线程的 Looper对象。Android系统的消息队列和消息循环都是针对具体线程的,一个线程可以存在(当然也可以不存在)一个消息队列和一个消 息循环(Looper),特定线程的消息只能分发给本线程,不能进行跨线程,跨进程通讯。但是创建的工作线程默认是没有消息循环和消息队列的,如果想让该 线程具有消息队列和消息循环,需要在线程中首先调用Looper.prepare()来创建消息队列,然后调用Looper.loop()进入消息循环。

    参考:http://my.unix-center.net/~Simon_fu/?p=652

    虽说 特定线程的消息只能分发给本线程,不能进行跨线程通讯,但是由于可以通过获得线程的Looper对象来进行曲线的实现不同线程间消息的传递,代码如下

     

    1. package com.mytest.handlertest;  
    2. import android.app.Activity;  
    3. import android.graphics.Color;  
    4. import android.os.Bundle;  
    5. import android.os.Handler;  
    6. import android.os.Looper;  
    7. import android.os.Message;  
    8. import android.util.Log;  
    9. import android.view.View;  
    10. import android.view.View.OnClickListener;  
    11. import android.view.ViewGroup.LayoutParams;  
    12. import android.widget.Button;  
    13. import android.widget.LinearLayout;  
    14. import android.widget.TextView;  
    15. public class HandlerTest extends Activity implements OnClickListener{  
    16.       
    17.     private String TAG = "HandlerTest";  
    18.     private boolean bpostRunnable = false;  
    19.       
    20.     private NoLooperThread noLooperThread = null;    
    21.     private OwnLooperThread ownLooperThread = null;    
    22.     private ReceiveMessageThread receiveMessageThread =null;  
    23.       
    24.     private Handler  mOtherThreadHandler=null;  
    25.     private EventHandler mHandler = null;   
    26.       
    27.     private Button btn1 = null;  
    28.     private Button btn2 = null;  
    29.     private Button btn3 = null;  
    30.     private Button btn4 = null;  
    31.     private Button btn5 = null;  
    32.     private Button btn6 = null;  
    33.     private TextView tv = null;  
    34.     /** Called when the activity is first created. */  
    35.     @Override  
    36.     public void onCreate(Bundle savedInstanceState) {  
    37.         super.onCreate(savedInstanceState);  
    38.          
    39.         LinearLayout layout = new LinearLayout(this);  
    40.         LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(25050);  
    41.         layout.setOrientation(LinearLayout.VERTICAL);  
    42.           
    43.         btn1 = new Button(this);  
    44.         btn1.setId(101);  
    45.         btn1.setText("message from main thread self");  
    46.         btn1.setOnClickListener(this);  
    47.         layout.addView(btn1, params);  
    48.           
    49.         btn2 = new Button(this);  
    50.         btn2.setId(102);  
    51.         btn2.setText("message from other thread to main thread");  
    52.         btn2.setOnClickListener(this);  
    53.         layout.addView(btn2,params);  
    54.           
    55.         btn3 = new Button(this);  
    56.         btn3.setId(103);  
    57.         btn3.setText("message to other thread from itself");  
    58.         btn3.setOnClickListener(this);  
    59.         layout.addView(btn3, params);  
    60.           
    61.         btn4 = new Button(this);  
    62.         btn4.setId(104);  
    63.         btn4.setText("message with Runnable as callback from other thread to main thread");  
    64.         btn4.setOnClickListener(this);  
    65.         layout.addView(btn4, params);  
    66.           
    67.         btn5 = new Button(this);  
    68.         btn5.setId(105);  
    69.         btn5.setText("main thread's message to other thread");  
    70.         btn5.setOnClickListener(this);  
    71.         layout.addView(btn5, params);  
    72.           
    73.         btn6 = new Button(this);  
    74.         btn6.setId(106);  
    75.         btn6.setText("exit");  
    76.         btn6.setOnClickListener(this);  
    77.         layout.addView(btn6, params);  
    78.           
    79.         tv = new TextView(this);  
    80.         tv.setTextColor(Color.WHITE);  
    81.         tv.setText("");  
    82.         params = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT);  
    83.         params.topMargin=10;  
    84.         layout.addView(tv, params);  
    85.           
    86.         setContentView(layout);  
    87.           
    88.         receiveMessageThread = new ReceiveMessageThread();  
    89.         receiveMessageThread.start();  
    90.           
    91.     }  
    92.       
    93.     class EventHandler extends Handler{  
    94.           
    95.         public EventHandler(Looper looper){  
    96.             super(looper);  
    97.         }  
    98.           
    99.         public EventHandler(){  
    100.             super();  
    101.         }  
    102.         @Override  
    103.         public void handleMessage(Message msg) {  
    104.             // TODO Auto-generated method stub  
    105.             super.handleMessage(msg);  
    106.             Log.e(TAG, "CurrentThread id:----------+>" + Thread.currentThread().getId());  
    107.             switch(msg.what){  
    108.             case 1:  
    109.                 tv.setText((String)msg.obj);  
    110.                 break;  
    111.                   
    112.             case 2:  
    113.                 tv.setText((String)msg.obj);  
    114.                 noLooperThread.stop();  
    115.                 break;  
    116.                   
    117.             case 3:  
    118.                 //不能在非主线程的线程里面更新UI,所以这里通过log打印信息  
    119.                 Log.e(TAG,(String)msg.obj);  
    120.                 ownLooperThread.stop();  
    121.                 break;  
    122.             default:  
    123.                 Log.e(TAG,(String)msg.obj);  
    124.                 break;  
    125.             }  
    126.         }  
    127.           
    128.     }  
    129.       
    130.       //ReceiveMessageThread has his own message queue by execute Looper.prepare();   
    131.     class ReceiveMessageThread extends Thread {  
    132.           
    133.         @Override  
    134.         public void run(){  
    135.             Looper.prepare();  
    136.             mOtherThreadHandler= new Handler(){  
    137.                 @Override  
    138.                 public void handleMessage(Message msg) {  
    139.                     // TODO Auto-generated method stub  
    140.                     super.handleMessage(msg);  
    141.                       
    142.                     Log.e(TAG,"-------+>"+(String)msg.obj);  
    143.                     Log.e(TAG, "CurrentThread id:----------+>" + Thread.currentThread().getId());  
    144.                       
    145.                 }  
    146.                    
    147.              };  
    148.              Log.e(TAG, "ReceiveMessageThread id:--------+>" + this.getId());   
    149.              Looper.loop();  
    150.         }  
    151.     }  
    152.       
    153.     class NoLooperThread extends Thread {  
    154.         private EventHandler mNoLooperThreadHandler;  
    155.         @Override  
    156.         public void run() {  
    157.               
    158.             Looper myLooper = Looper.myLooper();  
    159.             Looper mainLooper= Looper.getMainLooper();  
    160.               
    161.             String msgobj;  
    162.             if(null == myLooper){  
    163.                 //这里获得的是主线程的Looper,由于NoLooperThread没有自己的looper所以这里肯定会被执行  
    164.                 mNoLooperThreadHandler = new EventHandler(mainLooper);  
    165.                 msgobj = "NoLooperThread has no looper and handleMessage function executed in main thread!";   
    166.             } else{  
    167.                 mNoLooperThreadHandler = new EventHandler(myLooper);  
    168.                 msgobj = "This is from NoLooperThread self and handleMessage function executed in NoLooperThread!";   
    169.             }  
    170.               
    171.             mNoLooperThreadHandler.removeMessages(0);  
    172.               
    173.             if(bpostRunnable == false){  
    174.             //send message to main thread  
    175.                 Message msg = mNoLooperThreadHandler.obtainMessage(211, msgobj);  
    176.                 mNoLooperThreadHandler.sendMessage(msg);  
    177.                 Log.e(TAG, "NoLooperThread id:--------+>" + this.getId());   
    178.             }else{  
    179.                 //下面new出来的实现了Runnable接口的对象中run函数是在Main Thread中执行,不是在NoLooperThread中执行 记得 null == myLooper么  
    180.                 //注意Runnable是一个接口,它里面的run函数被执行时不会再新建一个线程    
    181.                 //您可以在run上加断点然后在eclipse调试中看它在哪个线程中执行    
    182.                   
    183.                 mNoLooperThreadHandler.post(new Runnable(){  
    184.                     public void run() {  
    185.                         // TODO Auto-generated method stub  
    186.                         tv.setText("update UI through handler post runnalbe mechanism!");    
    187.                         Log.e(TAG, "update UI id:--------+>" + Thread.currentThread().getId());   
    188.                         noLooperThread.stop();    
    189.                     }  
    190.                       
    191.                 });  
    192.             }  
    193.         }  
    194.           
    195.     }  
    196.       
    197.     class OwnLooperThread extends Thread{  
    198.         private EventHandler mOwnLooperThreadHandler = null;  
    199.           
    200.         @Override  
    201.         public void run() {  
    202.             Looper.prepare();  
    203.             Looper myLooper = Looper.myLooper();  
    204.             Looper mainLooper= Looper.getMainLooper();  
    205.               
    206.             String msgobj;  
    207.               
    208.             if(null == myLooper){  
    209.                 mOwnLooperThreadHandler = new EventHandler(mainLooper);  
    210.                 msgobj = "OwnLooperThread has no looper and handleMessage function executed in main thread!";   
    211.             }else{  
    212.                 mOwnLooperThreadHandler = new EventHandler(myLooper);  
    213.                 msgobj = "This is from OwnLooperThread self and handleMessage function executed in NoLooperThread!";  
    214.             }  
    215.               
    216.             mOwnLooperThreadHandler.removeMessages(0);  
    217.               
    218.             //给自己发送消息  
    219.             Message msg = mOwnLooperThreadHandler.obtainMessage(3,1,1,msgobj);  
    220.             mOwnLooperThreadHandler.sendMessage(msg);  
    221.             Looper.loop();  
    222.         }  
    223.     }  
    224.       
    225.     public void onClick(View v) {  
    226.         // TODO Auto-generated method stub  
    227.         switch(v.getId()){  
    228.         case 101:  
    229.             //主线程发送消息给自己  
    230.             Looper looper = Looper.myLooper();//get the Main looper related with the main thread   
    231.             //如果不给任何参数的话会用当前线程对应的Looper(这里就是Main Looper)为Handler里面的成员mLooper赋值  
    232.             mHandler = new EventHandler(looper);  
    233.             // 清除整个MessageQueue里的消息    
    234.             mHandler.removeMessages(0);  
    235.             String obj = "This main thread's message and received by itself!";  
    236.               
    237.             Message msg = mHandler.obtainMessage(1,1,1,obj);  
    238.             // 将Message对象送入到main thread的MessageQueue里面   
    239.             mHandler.sendMessage(msg);  
    240.             break;  
    241.         case 102:  
    242.             //other线程发送消息给主线程  
    243.             bpostRunnable = false;  
    244.             noLooperThread = new NoLooperThread();    
    245.             noLooperThread.start();    
    246.             break;  
    247.         case 103:  
    248.              //other thread获取它自己发送的消息    
    249.             tv.setText("please look at the error level log for other thread received message");    
    250.             ownLooperThread = new OwnLooperThread();    
    251.             ownLooperThread.start();    
    252.             break;    
    253.         case 104:        
    254.             //other thread通过Post Runnable方式发送消息给主线程    
    255.             bpostRunnable = true;    
    256.             noLooperThread = new NoLooperThread();    
    257.             noLooperThread.start();    
    258.             break;  
    259.         case 105:  
    260.             //主线程发送消息给other thread    
    261.             if(null!=mOtherThreadHandler){    
    262.             tv.setText("please look at the error level log for other thread received message from main thread");    
    263.             String msgObj = "message from mainThread";    
    264.             Message mainThreadMsg = mOtherThreadHandler.obtainMessage(111, msgObj);    
    265.             mOtherThreadHandler.sendMessage(mainThreadMsg);    
    266.             }    
    267.             break;    
    268.         case 106:    
    269.             finish();    
    270.             break;    
    271.         }  
    272.     }  
    273. }  

    使用Looper.myLooper静态方法可以取得当前线程的Looper对象。 

    使用mHandler = new EevntHandler(Looper.myLooper()); 可建立用来处理当前线程的Handler对象;其中,EevntHandler是Handler的子类。 

    使用mHandler = new EevntHandler(Looper.getMainLooper()); 可建立用来处理main线程的Handler对象;其中,EevntHandler是Handler的子类。 


    主线程发送消息: 

    在onClick的case 101中创建一个继承自Handler的EventHandler对象,然后获取一个消息,然后通过EventHandler对象调用 sendMessage把消息发送到主线程的MessageQueue中。主线程由系统创建,系统会给它建立一个Looper对象和 MessageQueue,所以可以接收消息。这里只要根据主线程的Looper对象初始化EventHandler对象,就可以通过 EventHandler对象发送消息到主线程的消息队列中。 

    主线程处理消息: 

    这里是通过 EventHandler的handleMessage函数处理的,其中收到的Message对象中what值为一的消息就是发送给它的,然后把消息里面附带的字符串在TextView上显示出来。 

    其他线程发送消息(这里是说不使用Runnable作为callback的消息): 

    首先bpostRunnable设为false,表示不通过Runnable方式进行消息相关的操作。然后启动线程noLooperThread, 然后以主线程的Looper对象为参数建立EventHandler的对象mNoLooperThreadHandler,然后获取一个Message并 把一个字符串赋值给它的一个成员obj,然后通过mNoLooperThreadHandler把消息发送到主线程的MessageQueue中。 

    主线程处理消息: 

    这里是通过 EventHandler的handleMessage函数处理的,其中收到的Message对象中what值为二的消息就是上面发送给它的,然后把消息里面附带的字符串在TextView上显示出来。 


    其他线程发送消息: 

    其他非主线程建立后没有自己的Looper对象,所以也没有MessageQueue,需要给非主线程发送消息时需要建立 MessageQueue以便接收消息。下面说明如何给自己建立MessageQueue和Looper对象。从OwnLooperThread的run 函数中可以看见有一个 Looper.prepare()调用,这个就是用来建立非主线程的MessageQueue和Looper对象的。 

    所以这里的发送消息过程是建立线程mOwnLooperThread,然后线程建立自己的Looper和MessageQueue对象,然后根据 上面建立的Looper对象建立对应的EventHandler对象mOwnLooperThreadHandler,然后由 mOwnLooperThreadHandler建立消息并且发送到自己的MessageQueue里面。 

    其他线程处理接收的消息: 

    线程要接收消息需要在run函数中调用Looper.loop(),然后loop函数会从MessageQueue中取出消息交给对应的 Handler对象 mOwnLooperThreadHandler处理,在mOwnLooperThreadHandler的handleMessage函数中会把 Message对象中what值为三的消息(上面发送的消息)在Log中打印出来,可以通过Logcat工具查看log。 

    其他线程发送消息(这里是说使用Runnable作为callback的消息): 

    首先 postRunnable设为true,表示通过Runnable方式进行消息相关的操作。然后启动线程noLooerThread, 然后以主线程的Looper对象为参数建立EventHandler的对象mNoLooperThreadHandler,然后获取一个Message并 把一个字符串赋值给它的一个成员obj,然后通过mNoLooperThreadHandler把消息发送到主线程的MessageQueue中。 

    主线程处理消息:
     

    主线程收到上面发送的Message后直接运行上面Runnable对象中的run函数进行相应的操作。run函数通过Log打印一个字符串,可以通过Logcat工具查看 log。 

    主线程发送消息: 

    这里首先要求线程receiveMessageThread运行(在onCreate函数中完成),并且准备好自己的 Looper和MessageQueue(这个通过ReceiveMessageThread中的run函数中的Looper.prepare()调用完 成),然后根据建立的Looper对象初始化Handler对象mOtherThreadHandler。然后在onClick的case 105中由mOtherThreadHandler建立一个消息(消息中有一个字符串对象)并且发送到线程receiveMessageThread中的 MessageQueue中。 

    其他线程处理接收的消息: 

    线程要接收消息需要在run函数中调用Looper.loop(),然后loop函数会从MessageQueue中取出消息交给对应的 Handler对象mOtherThreadHandler处理,在mOtherThreadHandler的handleMessage函数中会把 Message对象中的字符串对象在Log中打印出来,可以通过Logcat工具查看log。

    转自:http://www.javaeye.com/topic/717220

  • 相关阅读:
    服务端获取实际IP工具类
    vue-element-admin整合服务端代理api
    elemengui分页
    vue获取浏览器地址栏参数
    el-table-column动态判断显示性别男女
    nginx代理静态页面添加二级目录
    nginx配置代理指向Redis
    SpringBoot整合Redis日志反复提示Redis重连问题
    centos7安装Redis
    nohup启动jar包
  • 原文地址:https://www.cnblogs.com/firecode/p/2670853.html
Copyright © 2020-2023  润新知