Handler系列二:延迟执行原理

268 阅读3分钟

梳理Android Handler延迟执行的底层原理

概述

Android Handler延迟执行的底层机制涉及Handler、Message、MessageQueue以及Loope关键组件。 这一机制允许开发者在指定时间后,在主线程(UI线程)或其他线程中执行代码,而无需阻塞当前线程。

关键组件介绍

  1. Handler

    • 作用:用于发送和处理消息Message或Runnable对象。
    • 关联:与特定线程的Looper和MessageQueue相关联。
    • 发送:通过postDelayedsendMessageDelayed方法发送延迟消息或Runnable。
  2. Message

    • 内容:携带从Handler发送到MessageQueue的数据和描述信息,如延迟时间、回调等。
    • 排序:在MessageQueue中根据延迟时间排序,确保按顺序执行。
  3. MessageQueue

    • 存储:用于存放待处理的Message和Runnable对象。
    • 管理:负责消息的排序和取出,确保消息按延迟时间或插入顺序处理。
  4. Looper

    • 角色:每个线程可以有自己的Looper,用于管理该线程的MessageQueue。
    • 循环:Looper在其线程中循环调用MessageQueue的nextpoll方法,检查并处理消息。
    • 阻塞:当没有消息可处理时,Looper会阻塞当前线程,直到有消息到来或延迟时间到达。

延迟执行原理

  1. 计算延迟时间

    • Handler接收message的延迟时间(毫秒),并计算消息应在何时被处理。
  2. 插入MessageQueue

    • 根据计算出的延迟时间,将Message或Runnable插入到MessageQueue的适当位置。
    • MessageQueue内部维护一个按时间排序的队列,确保消息按顺序执行。
  3. Looper循环等待

    • Looper在其线程中循环等待,检查MessageQueue中的消息。
    • 如果没有立即需要处理的消息,且第一个消息是延迟消息且时间未到,Looper暂时不处理。会阻塞当前线程。
    • 使用nativePollOnce等方法实现阻塞和唤醒机制。
  4. 处理消息

    • 当消息到达其执行时间或Looper被唤醒时,从MessageQueue中取出消息。
    • 将消息传递给相应的Handler进行处理。
    • 对于postDelayed发送的Runnable,Handler直接调用其run方法执行。

注意事项

  • 线程安全:Handler与MessageQueue的交互是线程安全的,通过同步机制保证。
  • 内存泄漏:Handler作为内部类时可能持有外部类的引用,导致内存泄漏。应使用静态内部类加弱引用的方式避免。
  • 性能影响:过多或复杂的消息处理逻辑可能影响应用性能,需合理设计。

综上所述,Android Handler延迟执行的底层原理通过精确的时间控制和消息排序,结合Looper的循环等待机制,实现了在非阻塞状态下按预期时间执行代码的功能。


在Android开发中,Handler确实经常用于在UI线程和其他线程之间传递消息。为了有效管理Handler,特别是防止内存泄漏,我们通常会将Handler声明为静态内部类,并通过弱引用(WeakReference)持有外部类的引用。这样做可以防止因为Handler持有外部类的强引用而导致外部类(如Activity或Fragment)无法被垃圾回收。

下面是一个如何在Android中正确使用静态内部类加弱引用的Handler的示例代码:

public class MyActivity extends AppCompatActivity {

    // 静态内部类,防止Handler持有外部类的强引用
    private static class MyHandler extends Handler {

        // 使用弱引用来持有外部Activity的引用
        private final WeakReference<MyActivity> mActivityWeakReference;

        MyHandler(MyActivity activity) {
            mActivityWeakReference = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            MyActivity activity = mActivityWeakReference.get();
            if (activity != null) {
                // 安全地在这里使用activity
                // 根据msg.what处理不同的消息
            }
        }
    }

    private final MyHandler mHandler = new MyHandler(this);

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

        // 发送消息到Handler
        Message msg = Message.obtain();
        msg.what = 1; // 自定义的消息代码
        mHandler.sendMessage(msg);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 可以选择在这里移除所有消息和回调
        mHandler.removeCallbacksAndMessages(null);
    }
}