android Handler机制

来源:互联网 发布:颜如玉 知乎 编辑:程序博客网 时间:2024/04/29 21:35

1.为什么要使用Handlers?

    因为,我们当我们的主线程队列,如果处理一个消息超过5,android就会抛出一个 ANP(无响应)的消息,所以,我们需要把一些要处理比较长的消息,放在一个单独线程里面处理,把处理以后的结果,返回给主线程运行,就需要用的Handler来进行线程建的通信,关系如下图;

    

下面是Handler,Message,Message Queue之间的关系图

这个图有4个地方关系到handlers

1.Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(消息队列)

2.Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里;或者接收Looper(Message Queue取出)所送来的消息。

3. Message Queue(消息队列):用来存放线程放入的消息。

4.线程:UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue

每一个线程里可含有一个Looper对象以及一个MessageQueue数据结构。在你的应用程序里,可以定义Handler的子类别来接收Looper所送出的消息。

Message

作为handler接受的对象,我们有必要知道Message这个数据类型是个怎样的数据类型

从官方文档中我们可以知道message关于数据的字段

 

 

public int what

 

public int arg1

 

public int arg2

 

public Object obj

 

从上面的表格可以看出,message提供了一个对象来存储对象,而且,还提供了三个int字段用来存储少量int类型

当然,除了以上三个Message自有的字段外,我们还可以通过setData(Bundle b),来存储一个Bundle对象,来存储更丰富的数据类型,例如,图片等等.

在初始化我们的message的时候就可以为我们的Message默认字段赋值,注意赋值顺序!!!

2.发送消息的两种方式

方法一、

1.      Message msg = mHandler.obtainMessage();  

2.      msg.what = UPDATE_LISTVIEW;  

3.      msg.obj = current + "/" + total + "songs";  

4.      msg.sendToTarget();  

方法二、

1.  Message msg=new Message();  

2.      msg.arg1=i;  

3.      handler.sendMessage(msg);  

obtainmessage()是从消息池中拿来一个msg不需要另开辟空间newnew需要重新申请,效率低,obtianmessage可以循环利用第一种写法是messagehandler 类获取,从而可以直接向该handler对象发送消息,第二种写法是直接调用 handler的发送消息方法发送消息。

3.示例

线程间通信。在Android的应用启动时,会创建一个主线程,主线程会创建一个消息队列来处理各种消息。当你创建子线程时,你可以再你的子线程中拿到父线程中创建的Handler对象,就可以通过该对象向父线程的消息队列发送消息了。由于Android要求在UI线程中更新界面,因此,可以通过该方法在其它线程中更新界面。

1.通过Runnable在子线程中更新界面的例子

1)在主线程onCreate中创建Handler

public class HandlerTestApp extends Activity { 
        Handler mHandler;
 
        TextView mText;
 
       @Override
 
       public void onCreate(BundlesavedInstanceState) {
 
          super.onCreate(savedInstanceState);
 
          setContentView(R.layout.main);
 
           mHandler = newHandler();//
创建Handler 
           mText = (TextView)findViewById(R.id.text0);//
一个TextView 
       }

    2构建Runnable对象,在runnable中更新界面,此处,我们修改了TextView的文字.此处需要说明的是,Runnable对象可以再主线程中创建,也可以再子线程中创建。我们此处是在子线程中创建的。  
    
 RunnablemRunnable0 = new Runnable() 
    {
 
               @Override
 
               public void run() {
 
                       // TODO Auto-generated method stub
 
                       mText.setText("This is Update from ohter thread, Mouse DOWN");
 
               }
 
    };

3)创建子线程,在线程的run函数中,我们向主线程的消息队列发送了一个runnable来更新界面。

    private voidupdateUIByRunnable(){ 
          new Thread()  
        {                             public void run()  { 

//这句将抛出异常 

//mText.setText("This is Update from ohter thread,Mouse DOWN");
mHandler.post(mRunnable0);  
         }  
     }.start();

}

2.用Message在子线程中来更新界面

用Message更新界面与Runnable更新界面类似,只是需要修改几个地方。

    1)实现自己的Handler,对消息进行处理

    private classMyHandler extends Handler 
    {

       @Override 
        public void handleMessage(Messagemsg) { 
            // TODOAuto-generated method stub 
           super.handleMessage(msg); 
           switch(msg.what) 
            { 
            caseUPDATE://
在收到消息时,对界面进行更新 
               mText.setText("This update by message"); 
               break; 
            } 
        } 
    }

    2在新的线程中发送消息     
    privatevoid updateByMessage() 
    { 
        //
匿名对象 
         new Thread() 
         { 
               public void run() 
               { 
                   //mText.setText("This is Update from ohter thread, Mouse DOWN");

                   //UPDATE是一个自己定义的整数,代表了消息ID 
                   Message msg = mHandler.obtainMessage(UPDATE); 
                   mHandler.sendMessage(msg); 
               } 
         }.start(); 
    }

原创粉丝点击