返回

手撸一个Android经典线程通信框架:Handler,彻底摆脱消息阻塞!

IOS

Handler在Android中的线程通信详解

背景

Android开发中,线程通信一直是一个重要的议题。由于主线程负责UI绘制和用户交互,其他线程不能直接操作UI,因此需要使用特定的机制进行线程间通信。Handler便是Android系统提供的线程通信框架之一,也是使用最广泛的框架。

Handler的原理

Handler是一种消息处理机制,它可以将消息从一个线程发送到另一个线程。其工作原理如下:

  1. 创建Handler对象 :创建一个Handler对象并指定一个Looper对象。Looper负责消息的轮询和分发。
  2. 发送消息 :将消息发送到Handler的MessageQueue中。MessageQueue是一个FIFO队列,存储需要处理的消息。
  3. Looper轮询 :Looper不断轮询MessageQueue,如果有消息,将其取出并交给Handler处理。
  4. Handler处理消息 :Handler根据消息类型调用不同的回调函数来处理消息。

实现一个简单的Handler

为了深入理解Handler的原理,我们可以自己实现一个简单的Handler框架:

// Message类,包含消息类型、数据和目标Handler
class Message {

    private int what;
    private Object obj;
    private Handler target;

    public Message(int what, Object obj, Handler target) {
        this.what = what;
        this.obj = obj;
        this.target = target;
    }

    // getters
}

// Handler类,包含MessageQueue和Looper对象
class Handler {

    private Looper looper;
    private MessageQueue messageQueue;

    public Handler(Looper looper) {
        this.looper = looper;
        this.messageQueue = looper.getMessageQueue();
    }

    public void sendMessage(Message message) {
        messageQueue.enqueueMessage(message);
    }

    public void handleMessage(Message message) {
        // 处理消息
    }
}

// Looper类,负责消息轮询和分发
class Looper {

    private MessageQueue messageQueue;
    private Thread thread;

    public Looper() {
        this.messageQueue = new MessageQueue();
        this.thread = new Thread() {
            @Override
            public void run() {
                while (true) {
                    Message message = messageQueue.dequeueMessage();
                    if (message != null) {
                        message.getTarget().handleMessage(message);
                    }
                }
            }
        };
        thread.start();
    }

    public MessageQueue getMessageQueue() {
        return messageQueue;
    }
}

使用Handler

实现Handler后,即可用于线程通信:

// 创建子线程
Thread thread = new Thread() {
    @Override
    public void run() {
        // 创建Handler,指定Looper为当前线程的Looper
        Handler handler = new Handler(Looper.myLooper());

        // 创建消息,发送到主线程的Handler
        Message message = new Message(1, "Hello World", null);
        handler.sendMessage(message);
    }
};
thread.start();

// 主线程创建Handler,重写handleMessage()处理子线程消息
Handler handler = new Handler() {
    @Override
    public void handleMessage(Message message) {
        // 处理消息
        String text = (String) message.getObj();
        Log.d("TAG", "收到消息:" + text);
    }
};

常见问题解答

  1. 为什么要使用Handler?

    • Handler可以安全地在不同的线程之间传递消息,避免线程安全问题。
  2. 如何创建Handler?

    • 在主线程创建时,指定Looper为null,在子线程创建时,指定Looper为当前线程的Looper。
  3. 如何发送消息?

    • 使用Handler的sendMessage()方法。
  4. 如何处理消息?

    • 重写Handler的handleMessage()方法,根据消息类型进行处理。
  5. Handler和AsyncTask有什么区别?

    • AsyncTask是一个异步任务,用于在后台执行任务,而Handler则用于线程通信。