消息机制主要类

Post on Nov 06, 2021 by Wei Lin

Hanler类

Handler类的主要属性

成员变量 说明
Looper mLooper mLooper = Looper.myLooper(),指向线程的Looper对象
MessageQueue mQueue mQueue = mLooper.mQueue,指向Looper中的MessageQueue对象
Callback mCallback Handler自带的全局的Callback,用于处理消息回调
boolean mAsynchronous 表示是否异步处理消息,默认false
IMessenger mMessenger 实现基于消息的跨进程通信
public class Handler {
    //......
    public interface Callback {

        boolean handleMessage(@NonNull Message msg);
    }
    //......
    final Looper mLooper;
    final MessageQueue mQueue;
    final Callback mCallback;
    final boolean mAsynchronous;
    IMessenger mMessenger;
    //......
}

Handler类的构造方法

Handler一共有7个构造方法:

构造方法 说明
public Handler() 已弃用
public Handler(Callback callback) mCallback为Handler处理消息的全局Callback
public Handler(Looper looper) 使用Looper初始化
public Handler(Looper looper, Callback callback)  
public Handler(boolean async) 不支持APP调用,表示是否同步。普通消息都要在队列中排队等待,而异步消息则可以不用排队,直接执行。表示该Handler处理的消息在队列中优先级较高。
public Handler(Callback callback, boolean async)  
public Handler(Looper looper, Callback callback, boolean async)  

带Looper参数的最后都会调用到Handler(looper, callback, async),其余的最终都会调用到Handler(callback, async),并通过mLooper = Looper.myLooper()获取本线程的Looper对象。

Looper.java

public static @Nullable Looper myLooper() {
    return sThreadLocal.get();
}

构造方法的具体代码如下:

public Handler() {
    this(null, false);
}

public Handler(@Nullable Callback callback) {
    this(callback, false);
}

public Handler(@NonNull Looper looper) {
    this(looper, null, false);
}


public Handler(@NonNull Looper looper, @Nullable Callback callback) {
    this(looper, callback, false);
}

public Handler(boolean async) {
    this(null, async);
}


public Handler(@Nullable Callback callback, boolean async) {
    if (FIND_POTENTIAL_LEAKS) {
        final Class<? extends Handler> klass = getClass();
        if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                (klass.getModifiers() & Modifier.STATIC) == 0) {
            Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                klass.getCanonicalName());
        }
    }

    mLooper = Looper.myLooper();
    if (mLooper == null) {
        throw new RuntimeException(
            "Can't create handler inside thread " + Thread.currentThread()
                    + " that has not called Looper.prepare()");
    }
    mQueue = mLooper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}

@UnsupportedAppUsage
public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
    mLooper = looper;
    mQueue = looper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}

Handler类常用方法-sendMessage()

Base on: Android 11

方法 说明
sendMessage 发送一个msg
sendMessageDelayed 发送一个延迟消息,在指定的延迟(单位ms)后执行
sendEmptyMessage 只发送一个包含what值的message,是通过sendEmptyMessageDelayed实现的
sendEmptyMessageDelayed 只发送一个包含what值的message,在指定的延迟后(单位ms)执行
sendMessageAtTime 在指定的时间(注意不是延迟)发送消息。需要在当前系统时间基础上加一个延迟时间
sendMessageAtFrontOfQueue 将消息添加到消息队列头,即不用等待其它消息执行完
post 通过Runnable 接口在发送线程中实现消息处理的方法
其它post方法 如上


(1) sendMessage

说明:发送一个msg。

public final boolean sendMessage(@NonNull Message msg) {
    return sendMessageDelayed(msg, 0);
}


(2) sendMessageDelayed

说明:发送一个延迟消息,在指定的延迟(单位ms)后执行。

public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
    if (delayMillis < 0) {
        delayMillis = 0;
    }
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}


(3) sendEmptyMessage

说明:只发送一个包含what值的message,通过sendEmptyMessageDelayed(what, 0)实现。

public final boolean sendEmptyMessage(int what){
    return sendEmptyMessageDelayed(what, 0);
}


(4) sendEmptyMessageDelayed

说明:只发送一个包含what值的message,在指定的延迟后(单位ms)执行。

public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
    Message msg = Message.obtain();
    msg.what = what;
    return sendMessageDelayed(msg, delayMillis);
}


(5) sendMessageAtTime

说明:在指定的时刻(注意不是延迟)发送消息。

public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
    MessageQueue queue = mQueue;
    if (queue == null) {
        RuntimeException e = new RuntimeException(
                this + " sendMessageAtTime() called with no mQueue");
        Log.w("Looper", e.getMessage(), e);
        return false;
    }
    return enqueueMessage(queue, msg, uptimeMillis);
}

如果需要指定当前时间多少秒后发送消息,则需要在当前系统时间基础上加一个延迟时间,通常使用方法为:

sendMessageAtTime(msg, SystemClock.uptimeMillis()+delayMillis);


(6) sendMessageAtFrontOfQueue

说明:将消息添加到消息队列头,即不用等待其它消息执行完。其它方法都是按顺序添加到队列尾部。

public final boolean sendMessageAtFrontOfQueue(@NonNull Message msg) {
    MessageQueue queue = mQueue;
    if (queue == null) {
        RuntimeException e = new RuntimeException(
            this + " sendMessageAtTime() called with no mQueue");
        Log.w("Looper", e.getMessage(), e);
        return false;
    }
    return enqueueMessage(queue, msg, 0);
}

Handler类常用方法-post()

post()与sendMessage()实质是一样的,只是sendMessage()需要在接收消息的线程中写处理消息的代码,而使用post()的话,可以在发送消息的线程中写处理消息的代码。


(1) post

public final boolean post(@NonNull Runnable r) {
   return  sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
    Message m = Message.obtain();
    m.callback = r;
    return m;
}


(2) post系列方法

public final boolean postAtTime(@NonNull Runnable r, long uptimeMillis) {
    return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}
 
public final boolean postAtTime(
        @NonNull Runnable r, @Nullable Object token, long uptimeMillis) {
    return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
}

public final boolean postDelayed(@NonNull Runnable r, long delayMillis) {
    return sendMessageDelayed(getPostMessage(r), delayMillis);
}

/** @hide */
public final boolean postDelayed(Runnable r, int what, long delayMillis) {
    return sendMessageDelayed(getPostMessage(r).setWhat(what), delayMillis);
}
 
public final boolean postDelayed(
        @NonNull Runnable r, @Nullable Object token, long delayMillis) {
    return sendMessageDelayed(getPostMessage(r, token), delayMillis);
}
 
public final boolean postAtFrontOfQueue(@NonNull Runnable r) {
    return sendMessageAtFrontOfQueue(getPostMessage(r));
}

post()与sendMessage()区别

post一类的方法发送的是Runnable对象,但是最后还是会被封装成Message对象,将Runnable对象赋值给Message对象中的callback字段,然后交由sendMessageAtTime()方法发送出去。

在处理消息时,会在dispatchMessage()方法里首先被handleCallback(msg)方法执行,实际上就是执行Message对象里面的Runnable对象的run方法。

Handler类常用方法-处理消息

(1) obtainMessage

public final Message obtainMessage(){
    return Message.obtain(this);
}

public final Message obtainMessage(int what){
    return Message.obtain(this, what);
}

public final Message obtainMessage(int what, @Nullable Object obj) {
    return Message.obtain(this, what, obj);
}

public final Message obtainMessage(int what, int arg1, int arg2){
    return Message.obtain(this, what, arg1, arg2);
}

public final Message obtainMessage(int what, int arg1, int arg2, @Nullable Object obj) {
    return Message.obtain(this, what, arg1, arg2, obj);
}

obtainMessage共有5个重载方法,obtainMessage()是从消息池中返回一个msg,并将msg的属性置为obtainMessage()参数中设定的置。通过此方法避免了直接使用new Message()创建新对象,从而减少内存开销。


(2) removeMessages

public final void removeMessages(int what) {
    mQueue.removeMessages(this, what, null);
}
public final void removeMessages(int what, @Nullable Object object) {
    mQueue.removeMessages(this, what, object);
}

通过给定的参数,移除消息池中对应的消息。这两个重载函数最终调用的都是MessageQueue中的removeMessages(Handler h, int what, Object object)。


(3) dispatchMessage

public void dispatchMessage(@NonNull Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}

private static void handleCallback(Message message) {
    message.callback.run();
}

dispatchMessage()用于处理消息,在Looper中会调用Handler的dispatchMessage()。在dispatchMessage()中会根据msg.callback及mCallback执行不同的消息处理流程。


Handler按以下优先级开始处理这个消息:

(1)若Message自带了callback函数(即msg.callback),则交给callback处理;

(2)若Handler设置了全局的mCallback,则交给mCallback处理;

(3)交给Handler子类实现的handleMessage()来处理。

通常都会采用第3种方法。


(4) handleMessage

public void handleMessage(@NonNull Message msg) {
}


根据上述dispatchMessage()的流程,代码可能会执行到handleMessage()中,Handler类中的handleMessage()是一个空方法,需要子类实现它,在里面定义不同消息的执行方式。如下:

public class MainActivity extends AppCompatActivity {
    public static final int MsgNum = 1;
    //Android 11弃用了Handler默认的无参构造方法
    private final Handler handler = new Handler(Looper.getMainLooper()) {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MsgNum:
                    // 在这里可以进行UI操作
                    break;
                default:
                    break;
            }
        }
    };
    //......
}

Looper类

Looper类的主要属性

成员变量 说明
ThreadLocal sThreadLocal  
Looper sMainLooper sMainLooper = myLooper() 若当前线程为主线程,才会调用prepareMainLooper()给该变量赋值,表示主线程的Looper对象
Observer sObserver  
MessageQueue mQueue mQueue = new MessageQueue(quitAllowed) 在构造函数中初始化,每个Looper都有一个MessageQueue对象
Thread mThread mThread = Thread.currentThread();表示当前线程
boolean mInLoop 表示消息循环,即Looper.loop()是否在执行中
Printer mLogging  
long mTraceTag  
mSlowDispatchThresholdMs slow dispatch的阈值,单位ms,超过该阈值则打印slow dispatch的log
mSlowDeliveryThresholdMs slow delivery的阈值,单位ms,超过该阈值则打印slow delivery的log


public final class Looper {
    private static final String TAG = "Looper";
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    private static Looper sMainLooper;  // guarded by Looper.class
    private static Observer sObserver;
    final MessageQueue mQueue;
    final Thread mThread;
    private boolean mInLoop;
    private Printer mLogging;
    private long mTraceTag;
    private long mSlowDispatchThresholdMs;
    private long mSlowDeliveryThresholdMs;
    //......
}

Looper常用方法

方法 说明
static prepare(boolean quitAllowed) 为当前线程创建Looper对象,quitAllowed表示是否运行线程退出Looper循环
static void prepareMainLooper() 创建主线程Looper,开发者不需要调用
static Looper getMainLooper() 获取主线程Looper
static void loop() 开始消息循环
static boolean loopOnce(final Looper me, final long ident, final int thresholdOverride) 执行一个消息,由loop()在for循环中一直调用
static Looper myLooper() 获取当前线程的Looper对象,若没有(即在该线程没执行过prepare())则返回null
static MessageQueue myQueue() 获取当前线程的消息队列
boolean isCurrentThread() 判断使用该Looper的线程是否为Looper所在线程
void quit() 不安全地退出Looper循环,因为一些消息可能未执行
void quitSafely() 安全退出循环
Thread getThread() 获取Looper所在线程的引用
MessageQueue getQueue() 同myQueue(),只是非静态方法


(1) public static void prepare()

其作用是初始化当前线程作为Looper线程,即为当前线程创建Looper对象,quitAllowed表示是否允许线程退出Looper循环。

public static void prepare() {
    prepare(true);
}

private static void prepare(boolean quitAllowed) {
    //一个Looper只能调用一次prepare
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    sThreadLocal.set(new Looper(quitAllowed));
}

private Looper(boolean quitAllowed) {
    mQueue = new MessageQueue(quitAllowed);
    mThread = Thread.currentThread();
}

其中sThreadLocal是一个ThreadLocal对象,表示这是一个线程局部变量,只有本线程可以访问。ThreadLocal中存储数据的对象为ThreadLocalMap,其键为当前对象,值为Looper。所以,prepare()通过ThreadLocal机制,把调用线程和Looper关联在一起。

Looper对象内部封装了一个消息队列mQueue。


(2) public static void prepareMainLooper()

Looper的另一种创建方式。

/**
 * Initialize the current thread as a looper, marking it as an
 * application's main looper. See also: {@link #prepare()}
 *
 * @deprecated The main looper for your application is created by the Android environment,
 *   so you should never need to call this function yourself.
 */
@Deprecated
public static void prepareMainLooper() {
    prepare(false);
    synchronized (Looper.class) {
        if (sMainLooper != null) {
            throw new IllegalStateException("The main Looper has already been prepared.");
        }
        sMainLooper = myLooper();
    }
}

这个方法是应用程序被创造时系统自动调用的方法,开发者不需要调用这个方法。


(3) static void loop()

开启消息循环,最终调用的是loopOnce()。

/**
 * Run the message queue in this thread. Be sure to call
 * {@link #quit()} to end the loop.
 */
@SuppressWarnings("AndroidFrameworkBinderIdentity")
public static void loop() {
    final Looper me = myLooper();
    if (me == null) {
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }
    if (me.mInLoop) {
        Slog.w(TAG, "Loop again would have the queued messages be executed"
                + " before this one completed.");
    }

    me.mInLoop = true;

    // Make sure the identity of this thread is that of the local process,
    // and keep track of what that identity token actually is.
    Binder.clearCallingIdentity();
    final long ident = Binder.clearCallingIdentity();

    // Allow overriding a threshold with a system prop. e.g.
    // adb shell 'setprop log.looper.1000.main.slow 1 && stop && start'
    final int thresholdOverride =
            SystemProperties.getInt("log.looper."
                    + Process.myUid() + "."
                    + Thread.currentThread().getName()
                    + ".slow", 0);

    me.mSlowDeliveryDetected = false;

    for (;;) {
        if (!loopOnce(me, ident, thresholdOverride)) {
            return;
        }
    }
}

prepare()与loop()使用方法

开发者手动创建一个线程,默认是没有消息循环的。如果需要在该线程中处理消息,则需要创建Looper对象,通过调用静态方法Looper.prepare()。有了Looper对象后才能初始化Handler对象,最后再调用静态方法Looper.loop()开启循环。


thread.run()方法才是调用thread.start()时线程的执行代码,所以应该在run方法中调用Looper.prepare()和Looper.loop(),并且在中间写Handler处理消息的代码。

class LooperThread extends Thread {
    public Handler mHandler;
    public static final int MsgNum = 1;

    @Override
    public void run() {
        Looper.prepare();
        mHandler = new Handler(Looper.myLooper()) {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case MsgNum:
                        Log.d("LooperThread", "执行消息成功!");
                        break;
                    default:
                        break;
                }
            }
        };
        Looper.loop();
    }
}

注意:写在Looper.loop()之后的代码不会被执行,这个函数内部是一个循环,只有调用mHandler.getLooper().quit()后,loop才会中止,其后的代码才能得以运行。

Message类

Message类的主要属性

Message有4个public变量what、arg1、arg2、obj 可以存储消息进行传递。

成员变量 说明
int what 标识msg,接收消息的线程根据what执行特定的代码
int arg1 存放整型数据
int arg2 存放整型数据
Object obj 存放结构化数据的对象,如AppBindData、IBinder、Configuration、String等类


其它成员变量:

成员变量 说明
int flags =1表示正在使用,当Message处于消息队列中、处于消息池中或者Handler正在处理Message的时候;=0表示未使用,从消息池取出后flags置为0,进入消息队列时置为1
long when 用于存储发送消息的时间点,单位ms
Bundle data 存储比较复杂的数据
Handler target 处理消息的目标Handler对象
Runnable callback 执行该消息的Runnable接口
Message next 指向下一个Message,消息池中的Message是链表结构
public final class Message implements Parcelable {

    public int what;
    public int arg1;
    public int arg2;
    public Object obj;
    public Messenger replyTo;
    public static final int UID_NONE = -1;
    public int sendingUid = UID_NONE;
    public int workSourceUid = UID_NONE;
    static final int FLAG_IN_USE = 1 << 0;
    static final int FLAG_ASYNCHRONOUS = 1 << 1;
    static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE;
    int flags;
    public long when;
    Bundle data;
    Handler target;
    Runnable callback;
    Message next;
    public static final Object sPoolSync = new Object();
    private static Message sPool;
    private static int sPoolSize = 0;
    private static final int MAX_POOL_SIZE = 50;
    private static boolean gCheckRecycle = true;
    //......Method
}

Message的构造方法

(1) Message只有一个无参构造方法

/** Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}).
*/
public Message() {
}

而且官方注释也建议用Message.obtain()构造Message。


(2) Message有8个静态方法可以创建Message实例

public static Message obtain()
public static Message obtain(Message orig)
public static Message obtain(Handler h)
public static Message obtain(Handler h, Runnable callback)
public static Message obtain(Handler h, int what)
public static Message obtain(Handler h, int what, Object obj)
public static Message obtain(Handler h, int what, int arg1, int arg2)
public static Message obtain(Handler h, int what, int arg1, int arg2, Object obj)

而obtain()则会从消息池中取出一个Message,如果消息池为null才会执行new Message()。其它构造方法都会调用Message m = obtain(),然后将参数赋值给Message。

public static Message obtain() {
    synchronized (sPoolSync) {
        if (sPool != null) {
            Message m = sPool;
            sPool = m.next;
            m.next = null;
            m.flags = 0; // clear in-use flag
            sPoolSize--;
            return m;
        }
    }
    return new Message();
}

public static Message obtain(Message orig) {
    Message m = obtain();
    m.what = orig.what;
    m.arg1 = orig.arg1;
    m.arg2 = orig.arg2;
    m.obj = orig.obj;
    m.replyTo = orig.replyTo;
    m.sendingUid = orig.sendingUid;
    m.workSourceUid = orig.workSourceUid;
    if (orig.data != null) {
        m.data = new Bundle(orig.data);
    }
    m.target = orig.target;
    m.callback = orig.callback;

    return m;
}

public static Message obtain(Handler h) {
    Message m = obtain();
    m.target = h;

    return m;
}

public static Message obtain(Handler h, Runnable callback) {
    Message m = obtain();
    m.target = h;
    m.callback = callback;

    return m;
}

public static Message obtain(Handler h, int what) {
    Message m = obtain();
    m.target = h;
    m.what = what;

    return m;
}

public static Message obtain(Handler h, int what, Object obj) {
    Message m = obtain();
    m.target = h;
    m.what = what;
    m.obj = obj;

    return m;
}

public static Message obtain(Handler h, int what, int arg1, int arg2) {
    Message m = obtain();
    m.target = h;
    m.what = what;
    m.arg1 = arg1;
    m.arg2 = arg2;

    return m;
}

public static Message obtain(Handler h, int what,
        int arg1, int arg2, Object obj) {
    Message m = obtain();
    m.target = h;
    m.what = what;
    m.arg1 = arg1;
    m.arg2 = arg2;
    m.obj = obj;

    return m;
}

消息池与获取、回收Message

每个进程都维护一个消息池,消息池中存放的是未使用的Message(指的是不再消息队列中,此时flag=1),该消息池中的消息在底层用链表实现,sPool就相当于该链表的头指针,sPoolSize表示链表中Message的数量,MAX_POOL_SIZE表示链表中Message规定的最大数量。


为什么要使用消息池?

和线程池类似,它们在系统内都是使用较为频繁的对象,频繁地创建或销毁对系统资源的开销比较大,所以对于不再使用Message对象,可以将其成员变量初始化,然后重新放回消息池。待需要使用Message对象时,从消息池中取一个对象即可,若消息池中无多余Message,则需要new一个。

Message next;
public static final Object sPoolSync = new Object();
private static Message sPool;
private static int sPoolSize = 0;
private static final int MAX_POOL_SIZE = 50;

//obtain()从消息池中取出消息时,若sPool != null会改变链表头sPool和next指针的指向,然后链表节点数sPoolSize减1;若sPool == null,则执行new Message()。
public static Message obtain() {
    synchronized (sPoolSync) {
        if (sPool != null) {
            Message m = sPool;
            sPool = m.next;
            m.next = null;
            m.flags = 0; // clear in-use flag
            sPoolSize--;
            return m;
        }
    }
    return new Message();
}

public void recycle() {
    if (isInUse()) {
        if (gCheckRecycle) {
            throw new IllegalStateException("This message cannot be recycled because it "
                    + "is still in use.");
        }
        return;
    }
    recycleUnchecked();
}

//回收消息时,将Message中的成员变量初始化,若sPoolSize < MAX_POOL_SIZE,则改变链表头sPool和next指针的指向,链表节点数sPoolSize加1。若若sPoolSize >=MAX_POOL_SIZE则抛弃该Message对象
@UnsupportedAppUsage
void recycleUnchecked() {
    // Mark the message as in use while it remains in the recycled object pool.
    // Clear out all other details.
    flags = FLAG_IN_USE;
    what = 0;
    arg1 = 0;
    arg2 = 0;
    obj = null;
    replyTo = null;
    sendingUid = UID_NONE;
    workSourceUid = UID_NONE;
    when = 0;
    target = null;
    callback = null;
    data = null;

    synchronized (sPoolSync) {
        if (sPoolSize < MAX_POOL_SIZE) {
            next = sPool;
            sPool = this;
            sPoolSize++;
        }
    }
}

recycle()与recycleUnchecked()的作用都是消息回收,即将已经使用过的Message对象重新放回消息池。区别是recycle()最终调用的也是recycleUnchecked(),但调用之前会执行isInUse()的检查,主要供开发者使用。recycleUnchecked()在Looper.loop()中调用。

MessageQueue中的主要属性

成员变量 说明
boolean mQuitAllowed 标示消息队列是否可以被关闭
long mPtr 保存native代码中的MessageQueue的指针
Message mMessages 表示链表头指针指向的Message
mIdleHandlers 一个ArrayList 对象,MessageQueue没有其它Message时,即空闲时可以利用它来处理一些事物,该变量就是用于保存这些空闲时候要处理的事务
mFileDescriptorRecords  
IdleHandler[] mPendingIdleHandlers 保存将要被执行的IdleHandler
boolean mQuitting MessageQueue是否关闭
boolean mBlocked MessageQueue是否阻塞
int mNextBarrierToken  


MessageQueue.IdleHandler类的作用:

MessageQueue.IdleHandler可以用来在线程空闲的时候,指定一个操作。有点类似Handler.postDelayed(Runnable r, long delayMillis),都是在将来的某一个时间执行一个操作。

不过,使用IdleHandler的好处在于可以不用指定一个将来时间,只要线程空闲了,就可以执行它指定的操作。比较适合那种需要在将来执行操作,但是又不知道需要指定多少延迟时间的操作。

public final class MessageQueue {
    private static final String TAG = "MessageQueue";
    private static final boolean DEBUG = false;

    private final boolean mQuitAllowed;
    private long mPtr; // used by native code
    Message mMessages;
    private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
    private SparseArray<FileDescriptorRecord> mFileDescriptorRecords;
    private IdleHandler[] mPendingIdleHandlers;
    private boolean mQuitting;
    private boolean mBlocked;
    private int mNextBarrierToken;
    //......Method
}

简单使用示例

注意事项

  • 发送方必须有接收方Handler的引用;
  • handler.sendMessage()系列方式发送的消息,接收方应该重载handleMessage(Message msg)方法,否则收到消息无法执行相关动作;

子线程接收msg—使用HandlerThread

HandlerThread本质上是一个线程类,它继承了Thread,它有有自己的内部Looper对象,所以可以进行looper循环。创建HandlerThread后必须先调用HandlerThread.start()方法,Thread会先调用run方法,创建Looper对象。

public class MainActivity extends AppCompatActivity {

    public static final int MsgNum = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //创建并定义threadHandler
        Handler threadHandler= createHandlerThread();
        findViewById(R.id.Botton1).setOnClickListener(v -> {
            //构造Message并设置targetHandler与what值
            Message message =  Message.obtain(threadHandler,MsgNum);
            threadHandler.sendMessage(message);
//            message.sendToTarget();
        });

    }

    public Handler createHandlerThread(){
        //Step 1:创建一个线程,线程名字:handler-thread
        HandlerThread myHandlerThread = new HandlerThread( "handler-thread") ;
        //Step 2:必须先开启线程才能定义threadHandler
        myHandlerThread.start();

        //Step 3:在这个线程中创建一个handler对象
        return new Handler( myHandlerThread.getLooper() ){
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case MsgNum:
                        // 在这里可以进行子线程耗时操作,不能更新UI,但可以使用Toast
                        Toast.makeText(getApplicationContext(), "我是HandlerThread", Toast.LENGTH_SHORT).show();
                        break;
                    default:
                        break;
                }
            }
        };
    }
}

子线程接收msg—使用Thread

需要在线程的run()方法中使用Looper.prepare()和Looper.loop()方法为子线程创建Looper对象。

public class MainActivity extends AppCompatActivity {
    public String TAG = "HandlerDemo";
    public static final int MsgNum = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        findViewById(R.id.Botton1).setOnClickListener(v -> {
            LooperThread looperThread = new LooperThread();
            looperThread.start();
            //等待looperThread线程给Handler赋值,否则mHandler=null
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Message message = Message.obtain();
            message.what=MsgNum;
            looperThread.mHandler.sendMessage(message);
        });

    }
}

class LooperThread extends Thread {
    public Handler mHandler;
    public static final int MsgNum = 1;

    @Override
    public void run() {
        Looper.prepare();
        mHandler = new Handler(Looper.myLooper()) {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case MsgNum:
                        Log.d("LooperThread", "执行消息成功!");
                        break;
                    default:
                        break;
                }
            }
        };
        Looper.loop();
    }
}

主线程接收消息—sendMessage()


public class MainActivity extends AppCompatActivity {
    public String TAG = "HandlerDemo";
    public static final int MsgNum = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //获取主线程Looper,也可以用Looper.myLooper()
        Looper mainLooper = Looper.getMainLooper();
        Handler mainHanlder = new Handler(mainLooper) {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case MsgNum:
                        Log.d(TAG, "执行消息成功!");
                        break;
                    default:
                        break;
                }
            }
        };

        findViewById(R.id.Botton0).setOnClickListener(v -> {
            Message message = Message.obtain();
            message.what = MsgNum;
            mainHanlder.sendMessage(message);
        });
    }
}

主线程接收消息—post()

通过post发送消息是发送方自己写消息的执行代码,接收方不需要在handleMessage()写该消息的处理流程。post()的参数是一个Runnable接口。

public class MainActivity extends AppCompatActivity {
    public String TAG = "HandlerDemo";
    public static final int MsgNum = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //获取主线程Looper,也可以用Looper.myLooper()
        Looper mainLooper = Looper.getMainLooper();
        Handler mainHanlder = new Handler(mainLooper);

        findViewById(R.id.Botton0).setOnClickListener(v -> {
            mainHanlder.post(() -> Log.d(TAG, "执行Post消息成功!"));
        });
    }
}