Android基础知识(十):Handler的使用方式与注意事项

在使用Handler机制之前,需要向了解Handler机制的原理:Handler机制的实现与原理分析。
Handler使用方式因发送消息到消息队列的方式不同而不同,共有2中方式:Handler.sendMessage()和Handler.post()。
一、使用Handler.sendMessage()

  1. 线程切换(空消息)
    一个简单的例子如下,在主线程中创建一个Handler,其handlerMessage()方法是运行在主线程的,当在子线程发送一个消息时,handlerMessage()会接收到消息,从而实现了线程的切换以及消息的处理。

    上述的代码中,Handler发送的消息是一个空消息,如果只是单纯的发送一个空消息,那么可以使用Handler发送空消息的方法sendEmptyMessage(what)。
  2. 带数据的线程切换消息处理
    Handler可以发送带有数据的Message,Message对象中有一个Object类型的obj属性,用于携带消息数据。使用Handler发送带有数据的消息,只需要将发送的数据赋值给obj,然后在处理消息的时候再把数据取出来即可,如下所示。

    除了obj以外,Message还有两个int类型的属性:arg1、arg2可以用来发送一些简单的数据。其中之一就是what属性,what属性是int类型,用于标识消息。使用方式如下。

    对于多个带有不同数据,并且所需的消息处理逻辑不一样的Message,可以使用Message的what属性来对不同的消息进行标识

二、使用Handler.post()

Handler.post()的使用方式如下。

android handler模式使用 安卓handler使用_android handler模式使用


由Handler.post()的源码,可以得知Runnable会被封装成一个Message对象,然后通过sendMessge存放到MessageQueue中,封装的逻辑为:将Runnable赋值给Message的callback即可。

由Handler机制的实现与原理分析中对Handler源码的总结中,消息处理方式中,Message的callback的优先级最高,所以这个消息是由自己的callback也就是Runnable中的run方法进行处理的,而不再是Handler的handleMessage()方法。三、消息处理的线程

在前面的例子中,消息的处理都是在主线程,但是消息的处理事实上是运行在负责关系消息队列(MessageQueue)的Looper所在的线程的,而不一定是主线程。

android handler模式使用 安卓handler使用_主线程_02


如果创建一个Handler对象而没有给其指定它的Looper,那么它会默认使用当前线程的Looper。另外需要注意的是:主线程默认是有实现Looper.perpare()以及Looper.loop()方法的,也就是说如果指定Handler的Looper是主线程的Looper,那么不需要创建主线程的Looper以及开启Looper的消息轮询

在子线程使用Handler,并且使得默认为消息处理在子线程的代码例子如下。

android handler模式使用 安卓handler使用_Android_03


子线程使用Handler的几个注意事项:

  1. 在子线程使用Handler之前一定要先为子线程创建Looper
    创建Looper的方式是直接调用Looper.prepare()方法。前面讲过创建Handler对象时如果没有给它指定Looper,那么它默认会使用当前线程的Looper,而线程默认是没有Looper的
  2. 在同一个线程里,Looper.prepare()方法不能被调用两次
  3. 只有调用了Looper.loop()方法,Handler机制才能正常工作
  4. Looper.loop()方法一定在调用了Looper.prepare()方法之后调用
  5. 不要在主线程调用Looper.prepare()方法
    Android系统创建主线程的时候就已经调用了Looper.prepare()方法和Looper.loop()方法。
  6. 当在子线程使用Handler时,如果Handler不在需要发送和处理消息,那么一定要退出子线程的消息轮询
    Looper.loop()方法是死循环,如果不主动结束,那么其会一直运行,导致子线程一直运行而不结束。

四、为Handler指定Looper以及Handler的其他使用方法

  1. 为Handler指定Looper
    指定Handler的Looper方法如下。
  2. Handler的其他使用方法
    Handler除了提供post()和sendMessage()方法以外,还提供了一系列的发送消息的方法。比如延时发送消息和定时发送消息:

五、小知识点

  1. 使用Message.obtain()来获取Message
    在使用中,创建一个Message对象,并不推荐通过硬初始化(new)的方式,而是使用Message.obtain()方法。
    Android会为Message提供一个缓存池,把使用过的消息缓存起来
    ,方便下次使用。使用Message.obtain()方法获取一个消息时,会先从缓存池获取,如果缓存池没有消息,才会去创建消息,从而优化内存。
  2. 同一个Message不要发送两次
    由于Message都是存放到MessageQuue中存放的,如果一个Message对象已经在MessageQueue中,再次把它存放到MessageQueue时会报错。
  3. Android提供的实现Handler的类和方法
    Android中提供的实现Handler的类和方法:runOnUiThread()方法、View的post()方法、HandlerThread类等。

参考资料:Android Handler的使用方式和注意事项