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;
    }
}
相关推荐
sun0077006 小时前
android ndk编译valgrind
android
AI视觉网奇7 小时前
android studio 断点无效
android·ide·android studio
jiaxi的天空7 小时前
android studio gradle 访问不了
android·ide·android studio
No Silver Bullet8 小时前
android组包时会把从maven私服获取的包下载到本地吗
android
catchadmin8 小时前
PHP serialize 序列化完全指南
android·开发语言·php
tangweiguo0305198710 小时前
Kable使用指南:Android BLE开发的现代化解决方案
android·kotlin
00后程序员张12 小时前
iOS App 混淆与资源保护:iOS配置文件加密、ipa文件安全、代码与多媒体资源防护全流程指南
android·安全·ios·小程序·uni-app·cocoa·iphone
柳岸风14 小时前
Android Studio Meerkat | 2024.3.1 Gradle Tasks不展示
android·ide·android studio
编程乐学14 小时前
安卓原创--基于 Android 开发的菜单管理系统
android
whatever who cares16 小时前
android中ViewModel 和 onSaveInstanceState 的最佳使用方法
android