Handler源码分析
发布日期:2021-05-14 09:35:20 浏览次数:22 分类:精选文章

本文共 4549 字,大约阅读时间需要 15 分钟。

Handler机制:Android异步处理的核心

Handler的简单使用

Handler 是Android实现异步处理的核心工具,广泛用于在子线程中执行数据操作,并在操作完成后通过UI控件反馈结果。本文将深入分析Handler的工作原理及其在Android中的应用场景。

Step 1: 初始化Handler

Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.i("TAG", String.valueOf(msg.what));
}
};

Step 2: 发送空消息

handler.sendEmptyMessage(1);

Step 3: 查看 日志输出

可以在Android Studio中查看以下日志:

I/TAG: 1

Handler的基础概念

Handler机制由Handler、Message、MessageQueue和Looper四部分组成。每个部分在Android系统中都有特定的职责:

  • Handler (处理器):用于发送消息并执行异步回调。
  • Message (消息):包含发送的数据(如what、data等)。
  • MessageQueue (消息队列):存储Handler发送的消息,按时间顺序排列。
  • Looper (循环器):不断从MessageQueue中取出消息并调用Handler的handleMessage方法。

  • Handler源码分析

    理解Handler的内部逻辑工zung是掌握其工作原理的关键。

    Step 1: new Handler()的源码解析

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

    转化为:

    public Handler(Callback callback, boolean async) {
    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;
    }

    关键点Looper.myLooper()返回与当前线程关联的Looper实例。通常每个线程只能有一个Looper实例。


    Step 2: sendEmptyMessage的实现

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

    它内部调用:

    public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
    MessageQueue queue = mQueue;
    if (queue == null) {
    throw new RuntimeException("Looper has no message queue");
    }
    enqueueMessage(queue, msg, uptimeMillis);
    }

    最后调用:

    private boolean enqueueMessage(MessageQueue queue, Message msg, long when) {
    msg.target = this;
    // Msg打包后存入Queue
    return queue.enqueueMessage(msg, when);
    }

    关键点:无法直接使用子线程创建Handler,除非先调用Looper.prepare()


    Looper的创建与循环

    默认情况下,ActivityThread中的main方法会自动初始化Looper:

    public static void main(String[] args) {
    Looper.prepareMainLooper();
    // 线程创建与attached操作...
    Looper.loop();
    }

    关键点

    • Looper.prepareMainLooper():为主线程创建Looper实例。
    • Looper.loop():进入死循环,处理消息。

    Step 3: Looper团辅阶段

    public static void prepareMainLooper() {
    prepare(false);
    synchronized (Looper.class) {
    if (sMainLooper != null) {
    throw new IllegalStateException("The main Looper has already been prepared.");
    }
    sMainLooper = myLooper();
    }
    }
    // Internal method
    private static void prepare(boolean quitAllowed) {
    if (sThreadLocal.get() != null) {
    throw new RuntimeException("Only one Looper may be created per thread");
    }
    sThreadLocal.set(new Looper(quitAllowed));
    }

    关键点:每个线程只能有一个Looper实例。


    Step 4: Looper的死循环

    public static void loop() {
    final Looper me = myLooper();
    if (me == null) {
    throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }
    final MessageQueue queue = me.mQueue;
    for (;;) {
    Message msg = queue.next();
    if (msg == null) {
    return;
    }
    try {
    msg.target.dispatchMessage(msg);
    } finally {
    if (traceTag != 0) {
    Trace.traceEnd(traceTag);
    }
    }
    msg.recycleUnchecked();
    }
    }

    关键点:由于是死循环,programmer must小心存入队的操作以避免资源耗尽。


    Handler的注意事项

    1. 子线程使用Handler需要注意的事项

    在子线程中使用Handler需要执行以下步骤:

    public class ExampleRunnable implements Runnable {
    @Override
    public void run() {
    Looper.prepare();
    Handler handler = new Handler();
    handler.sendEmptyMessage(1);
    Looper.loop();
    }
    }

    错误实例

    new Thread(new Runnable() {
    @Override
    public void run() {
    Handler handler = new Handler() {
    // handleMessage...
    };
    handler.sendEmptyMessage(1);
    }
    }).start();

    错误原因:未调用Looper.prepare(),导致Handler无法获取到与线程关联的Looper。


    2. handleMessage所在的线程

    default情况下,msg.target(引用到Handler)的handleMessage方法会在Looper运行的线程被执行。这与ActivityThread有关。

    public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
    handleCallback(msg);
    } else {
    if (mCallback != null) {
    if (mCallback.handleMessage(msg)) {
    return;
    }
    }
    handleMessage(msg);
    }
    }
    • handleCallback()优先处理callback。
    • handleMessage()执行的是开发者定义的回调方法。

    3. UI操作的限制

    handleMessage方法只能在主线程/UI线程中执行。在子线程中操作UI控件会导致crash。


    4. Looper与Handler的关系

    通过msg.target = this,Message与当前线程的Handler关联。


    总结

    Handler机制是Android核心的异步处理工具,用于处理I/O密集型操作。通过Handler的简单使用,你可以轻松发送消息并在适当的位置处理事件。理解其内部机制有助于解决常见问题,如子线程使用Handler时的Looper准备问题。

    理解了以上内容后,你可以更自信地在实际开发中使用Handler进行异步操作。如果有任何疑问,请通过实验和调试进一步加深理解。

    上一篇:AsyncTask源码分析
    下一篇:OKR的制定规范

    发表评论

    最新留言

    关注你微信了!
    [***.104.42.241]2025年04月15日 17时00分52秒