Android中Handler总结

-
一、Handler的定义:

          主要接受子 线程发送的数据, 并用此数据配合主线程更新 UI.

          解释: 当应用程序启动时, Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI 控件,进行事件分发, 比如说, 你要是点击一个 Button ,Android会分发事件到Button上,来响应你的操作。  如果此时需要一个耗时的操作,例如: 联网读取数据,    或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,,如果你放在主线程中的话,界面会出现假死现象, 如果5秒钟还没有完成的话,,会收到Android系统的一个错误提示  "强制关闭".  这个时候我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,,Android主线程是线程不 安全的,也就是说,更新UI只能在主线程中更新,子线程中操作是危险的. 这个时候,Handler就出现了.,来解决这个复杂的问题 ,    由于Handler运行在主线程中(UI线程中),  它与子线程可以通过Message对象来传递数据, 这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象,(里面包含数据)  , 把这些消息放入主线程队列中,配合主线程进行更新UI。

二、Handler一些特点

        handler可以分发Message对象和Runnable对象到主线程中, 每个Handler实例,都会绑定到创建他的线程中(一般是位于主线程),
        它有两个作用: (1):  安排消息或Runnable 在某个主线程中某个地方执行, (2)安排一个动作在不同的线程中执行
     
        Handler中分发消息的一些方法
        post(Runnable)
        postAtTime(Runnable,long)
        postDelayed(Runnable long)
        sendEmptyMessage(int)
        sendMessage(Message)
        sendMessageAtTime(Message,long)
        sendMessageDelayed(Message,long)

        以上post类方法允许你排列一个Runnable对象到主线程队列中,
        sendMessage类方法, 允许你安排一个带数据的Message对象到队列中,等待更新.

三、Handler实例

      (1) 子类需要继承Hendler类,并重写handleMessage(Message msg) 方法, 用于接受线程数据

      以下为一个实例,它实现的功能为 : 通过线程修改界面Button的内容
  1. public class MyHandlerActivity extends Activity {
  2.     Button button;
  3.     MyHandler myHandler;

  4.     protected void onCreate(Bundle savedInstanceState) {
  5.         super.onCreate(savedInstanceState);
  6.         setContentView(R.layout.handlertest);

  7.         button = (Button) findViewById(R.id.button);
  8.         myHandler = new MyHandler();
  9.         // 当创建一个新的Handler实例时, 它会绑定到当前线程和消息的队列中,开始分发数据
  10.         // Handler有两个作用, (1) : 定时执行Message和Runnalbe 对象
  11.         // (2): 让一个动作,在不同的线程中执行.

  12.         // 它安排消息,用以下方法
  13.         // post(Runnable)
  14.         // postAtTime(Runnable,long)
  15.         // postDelayed(Runnable,long)
  16.         // sendEmptyMessage(int)
  17.         // sendMessage(Message);
  18.         // sendMessageAtTime(Message,long)
  19.         // sendMessageDelayed(Message,long)
  20.      
  21.         // 以上方法以 post开头的允许你处理Runnable对象
  22.         //sendMessage()允许你处理Message对象(Message里可以包含数据,)

  23.         MyThread m = new MyThread();
  24.         new Thread(m).start();
  25.     }

  26.     /**
  27.     * 接受消息,处理消息 ,此Handler会与当前主线程一块运行
  28.     * */

  29.     class MyHandler extends Handler {
  30.         public MyHandler() {
  31.         }

  32.         public MyHandler(Looper L) {
  33.             super(L);
  34.         }

  35.         // 子类必须重写此方法,接受数据
  36.         @Override
  37.         public void handleMessage(Message msg) {
  38.             // TODO Auto-generated method stub
  39.             Log.d("MyHandler", "handleMessage......");
  40.             super.handleMessage(msg);
  41.             // 此处可以更新UI
  42.             Bundle b = msg.getData();
  43.             String color = b.getString("color");
  44.             MyHandlerActivity.this.button.append(color);

  45.         }
  46.     }

  47.     class MyThread implements Runnable {
  48.         public void run() {

  49.             try {
  50.                 Thread.sleep(10000);
  51.             } catch (InterruptedException e) {
  52.                 // TODO Auto-generated catch block
  53.                 e.printStackTrace();
  54.             }

  55.             Log.d("thread.......", "mThread........");
  56.             Message msg = new Message();
  57.             Bundle b = new Bundle();// 存放数据
  58.             b.putString("color", "我的");
  59.             msg.setData(b);

  60.             MyHandlerActivity.this.myHandler.sendMessage(msg); // 向Handler发送消息,更新UI

  61.         }
  62.     }

  63. }

Handler的特点

  1. 传递Message。用于接受子线程发送的数据, 并用此数据配合主线程更新UI。

  在Android中,对于UI的操作通常需要放在主线程中进行操作。如果在子线程中有关于UI的操作,那么就需要把数据消息作为一个Message对象发送到消息队列中,然后,由Handler中的handlerMessage方法处理传过来的数据信息,并操作UI。当然,Handler对象是在主线程中初始化的,因为它需要绑定在主线程的消息队列中。

  类sendMessage(Message msg)方法实现发送消息的操作。 在初始化Handler对象时重写的handleMessage方法来接收Messgae并进行相关操作。

  2. 传递Runnable对象。用于通过Handler绑定的消息队列,安排不同操作的执行顺序。

  Handler对象在进行初始化的时候,会默认的自动绑定消息队列。利用类post方法,可以将Runnable对象发送到消息队列中,按照队列的机制按顺序执行不同的Runnable对象中的run方法。

Handler中分发消息的一些方法

  post(Runnable)

  postAtTime(Runnable,long)

  postDelayed(Runnable,long)

  sendEmptyMessage(int)

  sendMessage(Message)

  sendMessageAtTime(Message,long)

  sendMessageDelayed(Message,long)

Handler和多线程

  post方法虽然发送的是一个实现了Runnable接口的类对象,但是它并非创建了一个新线程,而是执行了该对象中的run方法。也就是说,整个run中的操作和主线程处于同一个线程。

  这样对于那些简单的操作,似乎并不会影响。但是对于耗时较长的操作,当它被加入到消息队列中之后执行会占用很长的时间,以至于处于同一线程的其他操作无法继续执行,就会出现“假死”。为了解决这个问题,就需要使得handler绑定到一个新开启线程的消息队列上,在这个处于另外线程的上的消息队列中处理传过来的Runnable对象和消息。

  这样,当使用sendMessage方法传递消息或者使用post方法传递Runnable对象时,就会把它们传递到与handler对象绑定的处于另外一个线程的消息队列中,它们将在另外的消息队列中被处理。而主线程还会在发送操作完成时候继续进行,不会影响当前的操作。

  这里需要注意,这里用到的多线程并非由Runnable对象开启的,而是ThreadHandler对象开启的。Runnable对象只是作为一个封装了操作的对象被传递,并未产生新线程。

 


  1. handler使用Message

    1.定义一个Handler

    2.重写消息处理函数

    3.发送消息

    //创建简单的View 
     import android.content.Context;   
     import android.graphics.Canvas;   
     import android.graphics.Color;   
     import android.graphics.Paint;   
     import android.graphics.Point;   
     import android.graphics.drawable.Drawable;   
     import android.view.View;   
        
     public class BounceView extends View {   
         float x = 40;   
            
         public BounceView(Context context) {    
              super(context);    
         }    
        
         @Override    
         protected void onDraw(Canvas canvas) {    
             x+=10;   
             Paint mPaint = new Paint();   
             mPaint.setAntiAlias(true);   
             mPaint.setColor(Color.GREEN);   
             canvas.drawCircle(x, 40, 40, mPaint);   
         }   
     }   
     
    //创建Activity 
     import android.app.Activity;   
     import android.content.Context;   
     import android.graphics.Canvas;   
     import android.graphics.Color;   
     import android.graphics.Paint;   
     import android.os.Bundle;   
     import android.os.Handler;   
     import android.os.Message;   
     import android.view.View;   
     import android.view.Window;   
        
     public class TestHandler extends Activity {   
          protected static final int GUIUPDATEIDENTIFIER = 0x101;    
             
          Thread myRefreshThread = null;    
          BounceView myBounceView = null;    
          //1.定义一个Handler(一般更新View) 
          Handler myHandler = new Handler() {   
               //2.重写消息处理函数 
               public void handleMessage(Message msg) {    
                    switch (msg.what) {    
                         //判断发送的消息 
                         case TestHandler.GUIUPDATEIDENTIFIER:    
                              //更新View 
                              myBounceView.invalidate();   
                              break;    
                    }    
                    super.handleMessage(msg);    
               }    
          };   
          public void onCreate(Bundle savedInstanceState) {    
               super.onCreate(savedInstanceState);    
               this.requestWindowFeature(Window.FEATURE_NO_TITLE);    
         
               this.myBounceView = new BounceView(this);   
               this.setContentView(this.myBounceView);    
               new Thread(new myThread()).start();   
          }    
         
          class myThread implements Runnable {    
               public void run() {   
                    while (!Thread.currentThread().isInterrupted()) {     
                         //3.发送消息 
                         Message message = new Message();  
                         //发送消息与处理函数里一致   
                         message.what = TestHandler.GUIUPDATEIDENTIFIER;    
                         //内部类调用外部类的变量 
                         TestHandler.this.myHandler.sendMessage(message);   
      
                         try {    
                              Thread.sleep(100);     
                         } catch (InterruptedException e) {    
                              Thread.currentThread().interrupt();    
                         }    
                    }    
               }    
          }    
     }  

    利用handler.post()更新UI

    1.创建一个Handler 2.调用Handler.post(Runnable r)方法 3.Runnable运行在UI所在线程,所以可以直接调用View.invalidate()

     import android.app.Activity;   
     import android.content.Context;   
     import android.graphics.Canvas;   
     import android.graphics.Color;   
     import android.graphics.Paint;   
     import android.os.Bundle;   
     import android.os.Handler;   
     import android.view.View;   
        
     public class TestHandler extends Activity {   
         private MyView myView;   
         private Handler mHandler;   
         public void onCreate(Bundle savedInstanceState) {   
             super.onCreate(savedInstanceState);   
             myView = new MyView(this);   
             //创建一个Handler 
             mHandler = new Handler(); 
             //调用Handler.post(Runnable r)方法 
             mHandler.post(new Runnable(){   
                 @Override   
                 public void run() {   
                     //直接调用View.invalidate(),更新组件 
                     myView.invalidate();   
                     //延迟5毫秒后执行线程 
                     mHandler.postDelayed(this, 5);   
                 }   
              });   
             setContentView(myView);   
         }   
            
         class MyView extends View{   
             private float x = 0f;   
             public MyView(Context context) {   
                 super(context);   
                    
         }   
             protected void onDraw(Canvas canvas) {   
                 super.onDraw(canvas);   
                 x+=1;   
                 Paint mPaint = new Paint();   
                 mPaint.setColor(Color.BLUE);   
                 canvas.drawRect(x, 40, x+40, 80, mPaint);   
             }   
                
         }   
     }  

    在线程里直接更新UI

     //在新线程里更新UI,可以直接使用postInvalidate()  
     
     public void onCreate(Bundle savedInstanceState) {       
            super.onCreate(savedInstanceState);       
            this.requestWindowFeature(Window.FEATURE_NO_TITLE);       
           
            myView = new MyView(this);   
            this.setContentView(this.myView);       
            new Thread(new myThread()).start();      
     }       
          
     class myThread implements Runnable {       
           public void run() {      
               while (!Thread.currentThread().isInterrupted()) {       
                  try {   
                        //更新UI 
                        myView.postInvalidate();    
                        Thread.sleep(100);        
                   } catch (InterruptedException e) {       
                        Thread.currentThread().interrupt();       
                   }       
               }       
           }       
     }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值