Android Handler Message多线程实例

http://blog.csdn.net/scorplopan/article/details/6227631

什么是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或者sendMessage方法向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对象来进行曲线的实现不同线程间消息的传递,代码如下


    package com.mytest.handlertest;  
    import android.app.Activity;  
    import android.graphics.Color;  
    import android.os.Bundle;  
    import android.os.Handler;  
    import android.os.Looper;  
    import android.os.Message;  
    import android.util.Log;  
    import android.view.View;  
    import android.view.View.OnClickListener;  
    import android.view.ViewGroup.LayoutParams;  
    import android.widget.Button;  
    import android.widget.LinearLayout;  
    import android.widget.TextView;  
    public class HandlerTest extends Activity implements OnClickListener{  
          
        private String TAG = "HandlerTest";  
        private boolean bpostRunnable = false;  
          
        private NoLooperThread noLooperThread = null;    
        private OwnLooperThread ownLooperThread = null;    
        private ReceiveMessageThread receiveMessageThread =null;  
          
        private Handler  mOtherThreadHandler=null;  
        private EventHandler mHandler = null;   
          
        private Button btn1 = null;  
        private Button btn2 = null;  
        private Button btn3 = null;  
        private Button btn4 = null;  
        private Button btn5 = null;  
        private Button btn6 = null;  
        private TextView tv = null;  
        /** Called when the activity is first created. */  
        @Override  
        public void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
             
            LinearLayout layout = new LinearLayout(this);  
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(250, 50);  
            layout.setOrientation(LinearLayout.VERTICAL);  
              
            btn1 = new Button(this);  
            btn1.setId(101);  
            btn1.setText("message from main thread self");  
            btn1.setOnClickListener(this);  
            layout.addView(btn1, params);  
              
            btn2 = new Button(this);  
            btn2.setId(102);  
            btn2.setText("message from other thread to main thread");  
            btn2.setOnClickListener(this);  
            layout.addView(btn2,params);  
              
            btn3 = new Button(this);  
            btn3.setId(103);  
            btn3.setText("message to other thread from itself");  
            btn3.setOnClickListener(this);  
            layout.addView(btn3, params);  
              
            btn4 = new Button(this);  
            btn4.setId(104);  
            btn4.setText("message with Runnable as callback from other thread to main thread");  
            btn4.setOnClickListener(this);  
            layout.addView(btn4, params);  
              
            btn5 = new Button(this);  
            btn5.setId(105);  
            btn5.setText("main thread's message to other thread");  
            btn5.setOnClickListener(this);  
            layout.addView(btn5, params);  
              
            btn6 = new Button(this);  
            btn6.setId(106);  
            btn6.setText("exit");  
            btn6.setOnClickListener(this);  
            layout.addView(btn6, params);  
              
            tv = new TextView(this);  
            tv.setTextColor(Color.WHITE);  
            tv.setText("");  
            params = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT);  
            params.topMargin=10;  
            layout.addView(tv, params);  
              
            setContentView(layout);  
              
            receiveMessageThread = new ReceiveMessageThread();  
            receiveMessageThread.start();  
              
        }  
          
        class EventHandler extends Handler{  
              
            public EventHandler(Looper looper){  
                super(looper);  
            }  
              
            public EventHandler(){  
                super();  
            }  
            @Override  
            public void handleMessage(Message msg) {  
                // TODO Auto-generated method stub  
                super.handleMessage(msg);  
                Log.e(TAG, "CurrentThread id:----------+>" + Thread.currentThread().getId());  
                switch(msg.what){  
                case 1:  
                    tv.setText((String)msg.obj);  
                    break;  
                      
                case 2:  
                    tv.setText((String)msg.obj);  
                    noLooperThread.stop();  
                    break;  
                      
                case 3:  
                    //不能在非主线程的线程里面更新UI,所以这里通过log打印信息  
                    Log.e(TAG,(String)msg.obj);  
                    ownLooperThread.stop();  
                    break;  
                default:  
                    Log.e(TAG,(String)msg.obj);  
                    break;  
                }  
            }  
              
        }  
          
          //ReceiveMessageThread has his own message queue by execute Looper.prepare();   
        class ReceiveMessageThread extends Thread {  
              
            @Override  
            public void run(){  
                Looper.prepare();  
                mOtherThreadHandler= new Handler(){  
                    @Override  
                    public void handleMessage(Message msg) {  
                        // TODO Auto-generated method stub  
                        super.handleMessage(msg);  
                          
                        Log.e(TAG,"-------+>"+(String)msg.obj);  
                        Log.e(TAG, "CurrentThread id:----------+>" + Thread.currentThread().getId());  
                          
                    }  
                       
                 };  
                 Log.e(TAG, "ReceiveMessageThread id:--------+>" + this.getId());   
                 Looper.loop();  
            }  
        }  
          
        class NoLooperThread extends Thread {  
            private EventHandler mNoLooperThreadHandler;  
            @Override  
            public void run() {  
                  
                Looper myLooper = Looper.myLooper();  
                Looper mainLooper= Looper.getMainLooper();  
                  
                String msgobj;  
                if(null == myLooper){  
                    //这里获得的是主线程的Looper,由于NoLooperThread没有自己的looper所以这里肯定会被执行  
                    mNoLooperThreadHandler = new EventHandler(mainLooper);  
                    msgobj = "NoLooperThread has no looper and handleMessage function executed in main thread!";   
                } else{  
                    mNoLooperThreadHandler = new EventHandler(myLooper);  
                    msgobj = "This is from NoLooperThread self and handleMessage function executed in NoLooperThread!";   
                }  
                  
                mNoLooperThreadHandler.removeMessages(0);  
                  
                if(bpostRunnable == false){  
                //send message to main thread  
                    Message msg = mNoLooperThreadHandler.obtainMessage(2, 1, 1, msgobj);  
                    mNoLooperThreadHandler.sendMessage(msg);  
                    Log.e(TAG, "NoLooperThread id:--------+>" + this.getId());   
                }else{  
                    //下面new出来的实现了Runnable接口的对象中run函数是在Main Thread中执行,不是在NoLooperThread中执行 记得 null == myLooper么  
                    //注意Runnable是一个接口,它里面的run函数被执行时不会再新建一个线程    
                    //您可以在run上加断点然后在eclipse调试中看它在哪个线程中执行    
                      
                    mNoLooperThreadHandler.post(new Runnable(){  
                        public void run() {  
                            // TODO Auto-generated method stub  
                            tv.setText("update UI through handler post runnalbe mechanism!");    
                            Log.e(TAG, "update UI id:--------+>" + Thread.currentThread().getId());   
                            noLooperThread.stop();    
                        }  
                          
                    });  
                }  
            }  
              
        }  
          
        class OwnLooperThread extends Thread{  
            private EventHandler mOwnLooperThreadHandler = null;  
              
            @Override  
            public void run() {  
                Looper.prepare();  
                Looper myLooper = Looper.myLooper();  
                Looper mainLooper= Looper.getMainLooper();  
                  
                String msgobj;  
                  
                if(null == myLooper){  
                    mOwnLooperThreadHandler = new EventHandler(mainLooper);  
                    msgobj = "OwnLooperThread has no looper and handleMessage function executed in main thread!";   
                }else{  
                    mOwnLooperThreadHandler = new EventHandler(myLooper);  
                    msgobj = "This is from OwnLooperThread self and handleMessage function executed in NoLooperThread!";  
                }  
                  
                mOwnLooperThreadHandler.removeMessages(0);  
                  
                //给自己发送消息  
                Message msg = mOwnLooperThreadHandler.obtainMessage(3,1,1,msgobj);  
                mOwnLooperThreadHandler.sendMessage(msg);  
                Looper.loop();  
            }  
        }  
          
        public void onClick(View v) {  
            // TODO Auto-generated method stub  
            switch(v.getId()){  
            case 101:  
                //主线程发送消息给自己  
                Looper looper = Looper.myLooper();//get the Main looper related with the main thread   
                //如果不给任何参数的话会用当前线程对应的Looper(这里就是Main Looper)为Handler里面的成员mLooper赋值  
                mHandler = new EventHandler(looper);  
                // 清除整个MessageQueue里的消息    
                mHandler.removeMessages(0);  
                String obj = "This main thread's message and received by itself!";  
                  
                Message msg = mHandler.obtainMessage(1,1,1,obj);  
                // 将Message对象送入到main thread的MessageQueue里面   
                mHandler.sendMessage(msg);  
                break;  
            case 102:  
                //other线程发送消息给主线程  
                bpostRunnable = false;  
                noLooperThread = new NoLooperThread();    
                noLooperThread.start();    
                break;  
            case 103:  
                 //other thread获取它自己发送的消息    
                tv.setText("please look at the error level log for other thread received message");    
                ownLooperThread = new OwnLooperThread();    
                ownLooperThread.start();    
                break;    
            case 104:        
                //other thread通过Post Runnable方式发送消息给主线程    
                bpostRunnable = true;    
                noLooperThread = new NoLooperThread();    
                noLooperThread.start();    
                break;  
            case 105:  
                //主线程发送消息给other thread    
                if(null!=mOtherThreadHandler){    
                tv.setText("please look at the error level log for other thread received message from main thread");    
                String msgObj = "message from mainThread";    
                Message mainThreadMsg = mOtherThreadHandler.obtainMessage(1, 1, 1, msgObj);    
                mOtherThreadHandler.sendMessage(mainThreadMsg);    
                }    
                break;    
            case 106:    
                finish();    
                break;    
            }  
        }  
    }  


使用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。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值