深入剖析Andorid中的消息机制

本文深入解析了Android消息机制,重点介绍了Message、Handler和Looper的作用及其交互方式。文章详细阐述了为何在子线程中更新UI时需要使用Handler,并通过源码分析展示了消息是如何在消息队列中流转并最终被处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android中的消息机制是学习andriod中比较难以理解的地方,理解好这一部分是灵活运用Handler的基础。

为什么使用handler?因为在android中,我们一般是不会在子线程中去操作图形界面的,典型的锂例子就是跟新进度条,改变进度条的值必须在主线程中进行。

学习消息机制之前先来介绍几个有关的类:

Message:

该类有几个用的比较多的属性 arg1,arg2,obj,what

官方解释:arg1 and arg2 are lower-cost alternatives to using setData() if you only need to store a few integer values.

arg1,arg2可以用来传递比较简单整型数据,使用它比将数据放入Bundle中的效率要高

obj:用来传递任何一个对象

what:存放消息码,使得接受者可以识别消息

Handler:

官方解释:

A Handler allows you to send and process Message and Runnable objects associated with a thread'sMessageQueue Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.

一个handler对象可以让Message对象和Runnable对象与一个线程的消息队列关联,每一个handler对象都和一个线程关联,当你创建一个handler,它就会与一个消息队列或者线程队列绑定,从那一刻起,它将会发送消息或者runnable到与他关联的队列,当消息或者runnable出队列时,就会被执行。

Looper:

官方解释:

Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, callprepare()in the thread that is to run the loop, and thenloop() to have it process messages until the loop is stopped.

该类主要用于管理一个线程的消息循环,一个线程默认是loop与之关联,创建一Looper,首先要调用prepare(),然后调用loop()不断的处理消息直到loop停止。

现在来分析一下源代码:

Looper:

 public static final Looper myLooper() {
        return (Looper)sThreadLocal.get();
    }


myLooper主要用于获得与当前线程对象关联的looper对象:

 public synchronized static final Looper getMainLooper() {
        return mMainLooper;
    }


getMainLooper用户获得与主线程关联的looper对象

注意:如果在主线程中调用myLooper那么这两种方法获得的对象时一样的

 public static final void loop() {
        Looper me = myLooper();
        MessageQueue queue = me.mQueue;
        while (true) {
            Message msg = queue.next(); // might block
            //if (!me.mRun) {
            //    break;
            //}
            if (msg != null) {
                if (msg.target == null) {
                    // No target is a magic identifier for the quit message.
                    return;
                }
                if (me.mLogging!= null) me.mLogging.println(
                        ">>>>> Dispatching to " + msg.target + " "
                        + msg.callback + ": " + msg.what
                        );
                msg.target.dispatchMessage(msg);
                if (me.mLogging!= null) me.mLogging.println(
                        "<<<<< Finished to    " + msg.target + " "
                        + msg.callback);
                msg.recycle();
            }
        }
    }


这是一个死循环,主要是从该线程的消息队列中不断的区消息,并发送给与之关联的handler对象。注意其中的msg.target.dispatchMessage(msg);msg.target就是与之关联的Handler对象。

Handler对象:

 public Handler() {
        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Handler> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }

        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = null;
    }


通过以上的代码,我们发现handler中的消息队列和一直关联的looper中的消息队列是同一个。

总而言之。每一个线程都有一个消息队列,而这个消息队列是交给与之关联的looper对象来管理的,而每个handler中又包含一个looper对象,所以他们操作的消息队列其实是一个。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值