当前位置:操作系统 > 安卓/Android >>

Android 消息处理 -- Looper 、Handler类

Windows编程的朋友可能知道Windows程序是消息驱动的,并且有全局的消息循环系统。而Android应用程序也是消息驱动的,按道理来说也应该提供消息循环机制。Android通过Looper、Handler来实现消息循环机制,Android消息循环是针对线程的(每个线程都可以有自己的消息队列和消息循环)。

在 Android 系统 ,这些工作由由由Looper 及 Handler 来完成。

先分析Looper类:
主要提供负责线程的消息循环和消息队列

    class LooperThread extends Thread {
        public Handler mHandler;
       
        public void run() {
            Looper.prepare();  // 准备。。。
           
            mHandler = new Handler() {
                public void handleMessage(Message msg) {  // 消息处理
                    // process incoming messages here
                }
            };
           
            Looper.loop();  // 进入消息循环
        }
    }

下面Looper类的准备函数:
private static final ThreadLocal sThreadLocal = new ThreadLocal();

   public static final void prepare() {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper());
    }


这里利用 ThreadLocal 线程局部存储变量将将Looper与调用线程关联起来。
而消息处理流程如何呢?
    /**
     *  Run the message queue in this thread. Be sure to call
     * {@link #quit()} to end the loop.
     */
    public static final void loop() {
        Looper me = myLooper();  // 线程中存储的Looper对象
        MessageQueue queue = me.mQueue;  // Looper类中的消息队列
        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);  // 利用 Target 注册的方法处理消息
                if (me.mLogging!= null) me.mLogging.println(
                        "<<<<< Finished to    " + msg.target + " "
                        + msg.callback);
                msg.recycle();
            }
        }
    }
   
可以通过Loop.myLooper()得到当前线程的Looper对象,通过Loop.getMainLooper()可以获得当前进程的主线程的Looper对象。


在android系统,UI线程就是消息的主线程,在 ActivityThread.java 中创建:
public static final void main(String[] args) {
     Looper.prepareMainLooper();
    
     Looper.loop(); //消息循环处理
}


-->
    public static final void prepareMainLooper() {
        prepare();
        setMainLooper(myLooper());
        if (Process.supportsProcesses()) {
            myLooper().mQueue.mQuitAllowed = false;
        }
    }


    private synchronized static void setMainLooper(Looper looper) {
        mMainLooper = looper;
    }
   
再来分析 Handler 类:
主要提供负责将消息加入到特定的Looper消息队列中,并分发和处理访消息队列中的消息,构造Handler的时候可以指定一个Looper对象,如果不指定则利用当前线程的Looper创建。www.zzzyk.com


请看如下代码即可明白:
    public Handler(Looper looper, Callback callback) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
    }
   
这里也同时告诉我们将消息放入到主线程的消息队列中,只需要创建Hanlde对象时以主线程的Looper创建即可。则sendMessage及handleMessage都会在主线程中进行处理。

再看如下变量:
    final MessageQueue mQueue;
    final Looper mLooper;
    final Callback mCallback;

这里也有 队列,Looper对象及回调函数类,通过 Handler 不同构造函数完成相应的操作。
简化使用队列及消息传递的复杂性,提供方便的调用方法。其中最重要的函数是:

    /**
     * Handle system messages here.
     */

补充:移动开发 , Android ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,