Android消息机制

Android消息机制是Android系统中处理线程间通信的核心部分。它通过消息队列(MessageQueue)和处理器(Handler)来实现异步处理任务,从而避免在主线程中进行耗时操作,保证应用的流畅性和响应性。

消息机制模型

Android消息机制模型就像一个持续运行的邮递系统,快递员(Handler)从仓库(MessageQueue)中取出信件(Message)并处理。

  • 消息队列(MessageQueue):这是仓库,用于存储所有待处理的快递包裹(消息)。消息队列按照消息的发送顺序或预定时间进行排序,确保消息能够及时处理。
  • 处理器(Handler):快递小哥,负责从信箱中取出信件并处理。每个Handler都关联着一个Looper,它负责管理消息循环。
  • 消息(Message):快递包裹,包含要传递的信息和处理的操作。Message对象不仅携带数据,还包含了处理方法的引用,确保消息能够被正确处理。
  • 消息循环(Looper):仓库的分拣人员,负责不断地检查信箱,并安排快递小哥取件和送件。每个线程在默认情况下没有Looper,需要调用Looper.prepare()来初始化。

消息机制架构

Handler、Looper和MessageQueue是Android消息处理机制的核心组成部分,它们之间的关系紧密相连。首先,每个线程可以拥有多个Handler,但每个线程只能有一个Looper,这个Looper是线程特有的,存储在ThreadLocal中。在Android的主线程(UI线程)中,系统已经为我们创建了一个Looper,因此我们无需再次创建。然而,在其他线程中,我们需要手动创建Looper。

Looper的作用是不断循环检查其MessageQueue,MessageQueue是Looper用来存储消息队列的容器。这些消息可以来自同一个线程中的不同Handler。简而言之,一个Looper可以处理多个Handler发送的消息,而这些消息都通过Looper所关联的MessageQueue进行管理。

消息机制的组件协同

Looper

Looper是消息循环的核心。通过Looper.prepare()方法为当前线程创建一个Looper对象,并初始化消息队列。每个线程可以有一个Looper,它通过不断循环来检查消息队列。

class MessageQueue {
    // 假设MessageQueue类已经实现了必要的方法和属性
    fun next(): Message? {
        // 实现获取下一个消息的逻辑
    }
}

class Message {
    // 假设Message类已经实现了必要的方法和属性
    var target: Handler? = null
    fun dispatchMessage(message: Message) {
        // 实现消息分发的逻辑
    }
}

class Handler {
    // 假设Handler类已经实现了必要的方法和属性
}

class Looper {
    private val queue: MessageQueue = MessageQueue()

    constructor() {
        // 在构造函数中初始化Looper
    }

    companion object {
        private val threadLocal: ThreadLocal<Looper> = ThreadLocal()

        fun prepare() {
            if (threadLocal.get() != null) {
                throw RuntimeException("Only one Looper may be created per thread")
            }
            threadLocal.set(Looper())
        }

        fun loop() {
            val looper = myLooper() ?: throw RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.")
            val queue = looper.queue
            while (true) {
                try {
                    val message = queue.next() ?: break
                    message?.target?.dispatchMessage(message)
                } catch (e: Exception) {
                    // 处理异常情况
                }
            }
        }

        fun myLooper(): Looper? = threadLocal.get()
    }
}

在这段代码中:

  • prepare()方法为当前线程创建并设置一个Looper对象。
  • loop()方法启动消息循环,从消息队列中不断地取出消息并分发给目标Handler进行处理。
  • myLooper()方法返回当前线程的Looper对象。
MessageQueue

MessageQueue负责存储和管理消息。消息以链表形式存储,当有新消息加入时,会根据消息的处理时间排序。

class Message {
    var when: Long = 0
    var next: Message? = null
    // 其他必要的属性和方法
}

class MessageQueue {
    private var head: Message? = null

    fun enqueueMessage(msg: Message, when: Long): Boolean = synchronized(this) {
        msg.when = when
        var p = head
        if (p == null || msg.when < p.when) {
            msg.next = p
            head = msg
        } else {
            var prev: Message? = null
            while (p != null && msg.when >= p.when) {
                prev = p
                p = p.next
            }
            msg.next = prev?.next
            prev?.next = msg
        }
        notifyAll()
        true
    }

    fun next(): Message? = synchronized(this) {
        var p = head
        while (p == null || p.when > System.currentTimeMillis()) {
            wait()
            p = head
        }
        head = p?.next
        p?.next = null
        p
    }
}

在这段代码中:

  • enqueueMessage()方法将消息按时间排序加入消息队列。
  • next()方法从消息队列中取出即将处理的消息,并在队列为空时等待。

Handler

Handler负责将消息加入队列,并在消息到达时进行处理。通过sendMessage()方法将消息发送到消息队列,并通过handleMessage()方法处理消息。

class Handler(looper: Looper) {
    private val looper: Looper = looper
    private val queue: MessageQueue = looper.queue

    fun sendMessage(msg: Message) {
        queue.enqueueMessage(msg, System.currentTimeMillis())
    }

    fun handleMessage(msg: Message) {
    }

    fun dispatchMessage(msg: Message) {
        if (msg.callback != null) {
            msg.callback.run()
        } else {
            handleMessage(msg)
        }
    }
}

在这段代码中:

  • sendMessage()方法将消息发送到消息队列。
  • dispatchMessage()方法处理消息,优先执行消息的回调方法(Runnable),否则调用handleMessage()

这里给出一段简化的Android消息机制源码,用于演示这些组件是如何协同工作的

class Message {
    Runnable action;
    long when;
    // 其他必要的属性和方法
}

class MessageQueue {
    private Message mMessages; // 用于模拟消息链表的头

    public Message next() {
        // 模拟获取下一个消息的逻辑
        synchronized (this) {
            // 这里只是示例,实际的实现会更复杂
            return mMessages; // 返回消息并从队列中移除
        }
    }

    public void enqueueMessage(Message msg, long when) {
        // 消息入队的逻辑
    }
}

class Handler {
    private MessageQueue mQueue;

    public Handler(MessageQueue queue) {
        mQueue = queue;
    }

    public void sendMessage(Message msg) {
        // 将消息发送到消息队列
        mQueue.enqueueMessage(msg, System.currentTimeMillis());
    }

    public void handleMessage(Message msg) {
        if (msg.action != null) {
            msg.action.run();
        }
    }
}

class Looper {
    private MessageQueue mQueue;
    private boolean mRunning;

    public Looper(MessageQueue queue) {
        mQueue = queue;
    }

    public void loop() {
        mRunning = true;
        while (mRunning) {
            Message msg = mQueue.next();
            if (msg != null) {
                Handler target = msg.getTarget();
                if (target != null) {
                    target.handleMessage(msg);
                }
            }
        }
    }

    public void quit() {
        mRunning = false;
    }
}

// 使用示例
MessageQueue queue = new MessageQueue();
Looper looper = new Looper(queue);
new Thread(new Runnable() {
    public void run() {
        looper.loop();
    }
}).start();

消息机制的典型使用

更新UI

使用Handler在后台线程完成一个耗时操作,然后在主线程更新UI。

import android.os.Handler
import android.os.Looper
import android.widget.TextView

class MainActivity : AppCompatActivity() {

    private lateinit var textView: TextView
    private val handler = object : Handler(Looper.getMainLooper()) {
        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
            // 这里执行UI更新操作
            textView.text = msg.obj as String
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        textView = findViewById(R.id.text_view)

        // 模拟后台线程耗时操作
        Thread {
            // 假设这里进行了一些耗时操作
            Thread.sleep(2000)

            // 当操作完成时,通过Handler发送消息回主线程
            val message = Message()
            message.obj = "操作完成,UI已更新"
            handler.sendMessage(message)
        }.start()
    }
}

在这个示例中:

  • 定义一个MainActivity类,它继承自AppCompatActivity。
  • 在onCreate方法中,设置了布局并获取了布局文件中的TextView控件引用,该控件用于展示文本信息。
  • 创建了一个Handler的匿名内部类实例,它与主线程的Looper关联。
  • 重写了handleMessage方法,以便在消息到达时执行UI更新操作。具体来说,将TextView的文本内容设置为消息对象中携带的字符串。
  • 启动了一个新的线程来模拟一个耗时操作。在这个示例中,使用Thread.sleep方法来模拟耗时过程。
  • 当耗时操作完成时,创建了一个Message对象,将操作结果封装为字符串,并设置为消息的对象,然后通过Handler将这个消息发送回主线程。

流程图

总结

以上便是消息机制的原理及组件解析,消息机制的运行过程,可以简单地用下图来理解。

  • 17
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值