一、关键概念概述

1. MessageQueue:MessageQueue是一种数据结构,用于存放消息。每个线程最多只能拥有一个MessageQueue实例。当创建一个线程时,并不会自动为其创建MessageQueue。通常情况下,我们需要使用Looper对象来管理线程的MessageQueue。主线程在创建时会自动创建一个默认的Looper对象,而Looper对象的创建过程会自动创建一个MessageQueue。对于其他非主线程,如果需要使用MessageQueue,可以通过调用prepare函数来实现。

2. Message:Message是MessageQueue中的一个对象,用于存储消息。一个MessageQueue中可以包含多个Message实例。获取Message实例的方法有多种,通常可以使用Message类的静态方法obtain()。该方法有多个重载版本可供选择。obtain()方法的实现方式是先从Message Pool(消息池)中查找是否有可用的Message实例,如果有则直接取出并返回;如果没有,则使用给定的参数创建一个新的Message实例。在调用removeMessages()方法时,将从MessageQueue中删除Message实例,并将其放回Message Pool中。除了上述方法,还可以通过Handler对象的obtainMessage()方法获取Message实例。

3. Looper:Looper是MessageQueue的管理器。每个MessageQueue都必须与一个Looper关联,而Looper对象的创建是通过prepare()函数来实现的。同时,每个Looper对象与一个线程关联。通过调用Looper.myLooper()方法可以获取当前线程的Looper对象。在创建Looper对象时,会同时创建一个与之关联的MessageQueue对象。需要注意的是,除了主线程有默认的Looper外,其他线程默认是没有MessageQueue对象的,因此无法接收Message。如果需要接收Message,可以为该线程自定义一个Looper对象(通过prepare()函数),这样该线程就拥有了自己的Looper对象和MessageQueue数据结构了。

Looper是Android消息循环机制的核心,它从MessageQueue中取出Message,然后交由Handler的handleMessage进行处理。处理完成后,调用Message.recycle()将其放入Message Pool中。

Handler是消息的处理者,它负责将需要传递的信息封装成Message,通过调用handler对象的obtainMessage()来实现;将消息传递给Looper,这是通过handler对象的sendMessage()来实现的。继而由Looper将Message放入MessageQueue中。当Looper对象看到MessageQueue中含有Message,就将其广播出去。该handler对象收到该消息后,调用相应的handler对象的handleMessage()方法对其进行处理。

Handler会关联一个单独的线程和消息队列。默认情况下,Handler关联主线程,虽然要提供Runnable参数,但默认是直接调用Runnable中的run()方法。也就是默认下会在主线程执行,如果在这里面的操作会有阻塞,界面也会卡住。如果要在其他线程执行,可以使用HandlerThread。

总结一下:looper相当于MessageQueue的创建者以及管理员。而Handler为处理者,处理MessageQueue两端的事务。每个线程都有一个looper,looper拥有一个message queue,looper是一个死循环,不停处理message queue中的消息。handler是方便多线程处理或异步处理而创建的数据结构,它拥有两个成员,一个指向handler被创建的线程的looper,一个是该线程的消息队列。所以,调用handler的post方法,实际上是把消息放到了该线程的消息队列(注意,不是当前线程)。每个消息有一个target成员,handler发送过去的消息会把该消息的target设置为自己。

在Android中,当looper收到消息后,会处理这些消息并将其发送给目标。这个过程看似绕道,实际上非常有必要。因为调用handler post是在子线程中进行的,而handler的处理方法则是在主线程中被调用的。这个过程伴随着一次线程调度。

为了解决这个问题,我们可以使用HandlerThread。它继承了Thread类,主要的作用是为应用程序提供一个独立的线程,并创建一个消息队列。通过使用自己的Looper,我们可以在自己的线程中分发和处理消息。这样可以避免在子线程中直接操作UI组件,从而保证了线程安全。

要使用Looper来实现Android的消息机制,我们需要重写Handler类的handleMessage()方法。同时,我们还需要创建一个HandlerThread对象,并通过它的getLooper()方法获取到Looper对象。然后将Looper传递给Handler对象,以便在主线程中处理消息。

需要注意的是,我们不能直接在HandlerThread的run()方法中处理消息。因为在这个方法中,我们还没有准备好开始执行消息分发和处理的工作。因此,我们需要重写HandlerThread的onLooperPrepared()方法,在这个方法中完成一些初始化工作,例如设置Handler对象等。这样一来,我们的代码就更加清晰、易于理解了。

总之,HandlerThread是一个简化了线程实现的消息机制的工具类。通过使用它,我们可以更方便地在自己的线程中处理消息,避免了在子线程中直接操作UI组件的问题。同时,通过重写onLooperPrepared()方法,我们还可以对Looper进行一些自定义的初始化工作,使代码更加清晰、易于维护。