Handler消息机制完全解析Handler解析

Handler

  • Handler构造方法
  • 创建消息obtainMessage
    发送消息sendMessage
    移除消息removeMessage
    处理消息dispatchMessage
    Handler一些特点
    Handler实例

Handler总是依附于创建时所在的线程,比如我们的Handler是在主线程中创建的,而在子线程中又无法直接对UI进行操作,于是我们就通过一系列的发送消息、入队、出队等环节,最后调用到了Handler的handleMessage()方法中,这时的handleMessage()方法已经是在主线程中运行的,因而我们当然可以在这里进行UI操作了。整个异步消息处理流程的示意图如下图所示:

异步消息处理流程

Handler

这便是我们平时直接使用的主角。继承Handler
重写其handleMessage()
方法来处理消息,在需要的时候调用sendMessage()
来发消息,剩下的就不用管了。现在来看看“我们不用管”的这部分都干了点啥。

构造方法

所有的构造方法最终会会调用两个实现,如果制定了Looper,则会调用三个参数的重载,否则会调用两个参数的重载。而后者则会调用Lopper.myLooper()
来获取looper。两个构造方法除了给mLooper
赋值外,还给mQueue
赋值为mLooper.mQueue
;给mCallback
赋值为指定的callback或null;给mAsynchronous
赋值为指定的boolean或false。 在两个参数的构造方法中,给上述四个成员赋值前有段if(FIND_POTENTIAL_LEAKS){}
包裹的代码段,该变量定义为private static final boolean FIND_POTENTIAL_LEAKS = false;
因此推断这部分是开发时调试用的,此处不做理会。

创建消息obtainMessage()

根据源码可以看出,所有该方法的重载都调用了Message.obtain()
对应的重载,可以看Message.obtain()的来龙去脉来了解,此处不再赘述。需要注意的是,每个重载都传入了this
参数并赋值给了message的target
。这里先记着就行,后面会介绍如何通过target
调用dispatchMessage()
处理消息。

发送消息sendMessage()

所有的sendEmptyMessage()
重载与sendMessageXXX()
以及postXXX()
最终都会调用enqueueMessage()
方法,该方法则调用queue.enqueueMessage()
方法将消息添加到消息队列。关于消息队列如何管理消息可以看MessageQueue的队列管理一文。

移除消息removeMessage()

所有的removeMessages()
重载与removeCallbacks()
重载最终都是调用mQueue.removeMessages()
方法,即通过MessageQueue来实现该操作。详细分析可以看MessageQueue的队列管理一文。

处理消息dispatchMessage()

消息处理最开始被调用的不是handleXXX()
方法,而是dispatchMessage()
方法。该方法会根据消息是否有callback
来判断该交给handleCallback()
还是handleMessage()
。前者直接调用参数中message
的message.calback.run()
解决问题,后者则是空方法体,需要我们开发者自己重写。

Handler一些特点

  • handler可以分发Message对象和Runnable对象到主线程中, 每个Handler实例,都会绑定到创建他的线程中(一般是位于主线程),它有两个作用:

    • (1)安排消息或Runnable 在某个主线程中某个地方执行;
    • (2)安排一个动作在不同的线程中执行。

Handler实例

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

  • 以下为一个实例,它实现的功能为:通过线程修改界面Button的内容

    public class MyHandlerActivity extends Activity { 
      Button button; 
      MyHandler myHandler; 
    
      protected void onCreate(Bundle savedInstanceState) { 
          super。onCreate(savedInstanceState); 
          setContentView(R。layout。handlertest); 
    
          button = (Button) findViewById(R。id。button); 
          myHandler = new MyHandler(); 
          // 当创建一个新的Handler实例时, 它会绑定到当前线程和消息的队列中,开始分发数据 
          // Handler有两个作用, (1) : 定时执行Message和Runnalbe 对象 
          // (2): 让一个动作,在不同的线程中执行。 
    
          // 它安排消息,用以下方法 
          // post(Runnable) 
          // postAtTime(Runnable,long) 
          // postDelayed(Runnable,long) 
          // sendEmptyMessage(int) 
          // sendMessage(Message); 
          // sendMessageAtTime(Message,long) 
          // sendMessageDelayed(Message,long) 
    
          // 以上方法以 post开头的允许你处理Runnable对象 
          //sendMessage()允许你处理Message对象(Message里可以包含数据,) 
    
          MyThread m = new MyThread(); 
          new Thread(m)。start(); 
      } 
    
      /** 
      * 接受消息,处理消息 ,此Handler会与当前主线程一块运行 
      * */ 
    
      class MyHandler extends Handler { 
          public MyHandler() { 
          } 
    
          public MyHandler(Looper L) { 
              super(L); 
          } 
    
          // 子类必须重写此方法,接受数据 
          @Override 
          public void handleMessage(Message msg) { 
              // TODO Auto-generated method stub 
              Log。d("MyHandler""handleMessage。。。。。。"); 
              super。handleMessage(msg); 
              // 此处可以更新UI 
              Bundle b = msg。getData(); 
              String color = b。getString("color"); 
              MyHandlerActivity。this。button。append(color); 
    
          } 
      } 
    
      class MyThread implements Runnable { 
          public void run() { 
    
              try { 
                  Thread。sleep(10000); 
              } catch (InterruptedException e) { 
                  // TODO Auto-generated catch block 
                  e。printStackTrace(); 
              } 
    
              Log。d("thread。。。。。。。""mThread。。。。。。。。"); 
              Message msg = new Message(); 
              Bundle b = new Bundle();// 存放数据 
              b。putString("color""我的"); 
              msg。setData(b); 
    
              MyHandlerActivity。this。myHandler。sendMessage(msg); // 向Handler发送消息,更新UI 
    
          } 
      } 
    }复制代码

    如果你觉
    得此文对您有所帮助,欢迎入群 QQ交流群 :232203809
    微信公众号:终端研发部

技术+职场

你可能感兴趣的:(Handler消息机制完全解析Handler解析)