Handle

让我来解释 Handler 的核心概念:

为什么需要 Handler?

Android 规定只能在主线程(UI线程)更新UI

但耗时操作(如网络请求、文件IO)不能在主线程执行

需要一个机制在子线程和主线程之间传递消息,这就是 Handler 的主要作用

Handler 的核心组件:

Handler:消息的发送和处理者

Message:消息对象,包含要传递的信息

MessageQueue:消息队列,用于存储消息

Looper:消息循环器,不断从 MessageQueue 中取出消息并交给 Handler 处理

工作流程:

Looper 通过 ThreadLocal 确保每个线程最多只有一个 Looper 实例

主线程(UI线程)默认已经创建了 Looper,子线程需要手动创建

Handler 发送消息(Message)到 MessageQueue

Looper 不断循环从 MessageQueue 取出消息,分发给对应的 Handler 处理

与后端开发的对比:

类似于生产者-消费者模式

Handler 类似于消息的生产者和消费者

MessageQueue 类似于消息队列(如 RabbitMQ)

Looper 类似于消息队列的消费者监听器

我已经在代码示例中展示了 Handler 的基本使用方式和内部原理。您可以看到:

如何创建 Handler 并处理消息

如何在子线程中发送消息

Looper 的实现原理

MessageQueue 的消息管理机制

这种设计的优点是:

实现了线程间的安全通信

避免了线程同步的复杂性

统一了异步任务的处理方式

java 复制代码
// 1. Handler 的基本使用
public class MainActivity extends Activity {
    private Handler mHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_UPDATE_UI:
                    // 在主线程更新UI
                    textView.setText("更新UI");
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        // 在子线程执行耗时操作
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 模拟网络请求
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                
                // 通过Handler发送消息到主线程
                Message msg = Message.obtain();
                msg.what = MSG_UPDATE_UI;
                mHandler.sendMessage(msg);
                
                // 或者使用post方法
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        // 这个代码块会在主线程执行
                        textView.setText("更新UI");
                    }
                });
            }
        }).start();
    }
}

// 2. Handler 内部原理示意
public class Looper {
    // 每个线程只能有一个Looper
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    final MessageQueue mQueue;  // 消息队列
    
    private Looper() {
        mQueue = new MessageQueue();
    }
    
    // 为当前线程创建Looper
    public static void prepare() {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper());
    }
    
    // 开启消息循环
    public static void loop() {
        final Looper me = myLooper();
        final MessageQueue queue = me.mQueue;
        
        for (;;) {
            Message msg = queue.next(); // 可能会阻塞
            if (msg == null) {
                return;
            }
            // 分发消息到对应的Handler
            msg.target.dispatchMessage(msg);
        }
    }
}

// 3. 消息队列示意
public class MessageQueue {
    Message mMessages;  // 消息链表的头部
    
    // 取出一条消息
    Message next() {
        for (;;) {
            synchronized (this) {
                // 取出消息链表中的第一条消息
                Message msg = mMessages;
                if (msg != null) {
                    mMessages = msg.next;
                    return msg;
                }
                // 如果没有消息,就等待
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
    }
    
    // 插入一条消息
    boolean enqueueMessage(Message msg, long when) {
        synchronized (this) {
            msg.when = when;
            Message p = mMessages;
            if (p == null || when == 0 || when < p.when) {
                msg.next = p;
                mMessages = msg;
            } else {
                Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                }
                msg.next = p;
                prev.next = msg;
            }
            notify();  // 唤醒等待的线程
        }
        return true;
    }
}
相关推荐
GitLqr4 小时前
Flutter 3.44 插件内置 Kotlin (KGP) 双向兼容适配指南
android·flutter·dart
随遇丿而安8 小时前
第11周:Activity 跳转与传值 + 跳转优化
android
私人珍藏库9 小时前
[Android] BBLL 开源第三方B哩电视TV端
android·app·生活·工具·多功能
杉氧11 小时前
跨平台资源管理:一套代码如何搞定 Android、iOS 和 Web 的图片与多语言?
android·架构·android jetpack
安卓修改大师12 小时前
安卓修改大师实战:从反编译到定制的完整APK修改指南
android
柚鸥ASO优化14 小时前
安卓APP推广的“降本增效”密码:守好商店内,打好商店外
android·aso优化
我是一颗柠檬14 小时前
【Java项目技术亮点】EXPLAIN深度分析与慢查询治理
android·java·开发语言
Android-Flutter14 小时前
android compose shadow 阴影 使用
android·kotlin·compose
帅次15 小时前
Android 高级工程师面试:Java 多线程与并发 近1年高频追问 22 题
android·java·面试
2501_9437823515 小时前
【共创季稿事节】摩斯电码转换器:编码表与双向转换的实现
android·华为·鸿蒙·鸿蒙系统