Android 消息处理Handler、 Message 、MessageQueue、Looper、Thread协调配合

本文深入探讨了Android应用中界面控制的核心原则——UI线程控制与子线程交互方式,重点解析了Handler机制如何在不同线程间传递消息并处理UI更新,包括Handler的声明、回调机制以及其与Looper、MessageQueue之间的交互流程。

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

android界面控制在ui线程里面,任何子线程都不允许直接操作ui而是借助handler或者activity的post方法等。handler又是如何处理线程间通信的?

1、Handler的声明放在ui主线程中声明然后传递给子线程:

		Handler handler=new Handler()
		{
			public void handleMessage(android.os.Message msg) {
				
			};
		};

Handler的源码:

    public Handler() {
        this(null, false);
    }
    public Handler(Callback callback, boolean async) {
        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 = callback;
        mAsynchronous = async;
    }
我们主要看黑色部分,函数调用 Looper.mylooper(),返回得到一个looper实例。该实例有个mQueue的成员变量属于MessageQueue的类型。

mCallback为null,mAsynchrous 为false 。

callback可以指定message的处理回调,而不是使用handler的默认handMessage()处理消息的回调。

mAsynchrous 表示该handle是否可以处理异步消息目前还不清楚如何区别别的消息类型。




先看下Looper

public class Looper {
    private static final String TAG = "Looper";

    // sThreadLocal.get() will return null unless you've called prepare().
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    private static Looper sMainLooper;  // guarded by Looper.class

    final MessageQueue mQueue;
    final Thread mThread;
    volatile boolean mRun;

    private Printer mLogging;

创建handler的时候便可以通过Looper.mylooper得到当前线程的looper 通过looper可以得到当前线程的消息队列 mMessageQueue 。Handler调用sendMessage的时候将message压入mMessageQueue。到此为止消息已经成功加入到消息队列当中,那么消息是什么时候,怎么样处理地呢?

回头看看Looper这个类,在创建 Handler的时候 Looper.mylooper()这个Looper的静态方法又是如何得到looper的呢。查找looper的成员函数,可以找到我们熟悉的Looper.prepare()以及Looper.prepareMain()由此可断定,当系统启动的时候即当ui主线程创建的时候android 内部便调用了Looper.prepareMainLooper()方法

   /**
     * Initialize the current thread as a looper, marking it as an
     * application's main looper. The main looper for your application
     * is created by the Android environment, so you should never need
     * to call this function yourself.  See also: {@link #prepare()}
     */
    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }
再调用完此方法后便调用Looper.looper()方法,详情参考android源码。可以看到looper方法里面有个循环不断的从mMessageQueue里面拿出消息,再交由message的target的dispatchMessage处理。message的target是一个handler对象,在加入mMessageQueue的时候添加:

    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }
disPatchMessage方法如下:

    /**
     * Handle system messages here.
     */
    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

Message 自己有callback是一个runable ,handler也有个Callback 是一个handler类的内部接口,当希望使用自己接口来处理消息回调,可以实现该内部接口的handleMessage(Message msg) 方法。当处理消息的时候优先使用message的callback 其次使用传入handler的callback,再就是handler的handmessage的方法。

这样一波三折子线程的message通过handler传入到主线程的消息队列中并且在主线中执行。这样便可以在子线程中操作ui线程的东西。



                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值