android的handler、looper、Message之间的关系

handler:绑定到一个线程上,一个线程能够有多个handler安全

looper:线程跟looper是一一对应的,因此looper不能被调用两次不然会抛出异常async

messge:handler利用message来携带消息ide

messagQueue:用来状态message,一个looper对应一个消息队列函数

如何来判断一个消息队列对应一个handler呢,在sendmessage中获取到一个消息队列的持有者looperoop

looper的两个方法:prepare()和loop()ui

1.this

复制代码

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

复制代码

给当前线程一个设定一个looper实例spa

2.线程

private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mRun = true;
        mThread = Thread.currentThread();
}

给这个looper建立一个消息队列(在构造函数中),并返回当前的线程对象

3.

复制代码

public static void loop() {
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        final MessageQueue queue = me.mQueue;

        // Make sure the identity of this thread is that of the local process,
        // and keep track of what that identity token actually is.
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();

        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }

            // This must be in a local variable, in case a UI event sets the logger
            Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }

            msg.target.dispatchMessage(msg);

            if (logging != null) {
                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
            }

            // Make sure that during the course of dispatching the
            // identity of the thread wasn't corrupted.
            final long newIdent = Binder.clearCallingIdentity();
            if (ident != newIdent) {
                Log.wtf(TAG, "Thread identity changed from 0x"
                        + Long.toHexString(ident) + " to 0x"
                        + Long.toHexString(newIdent) + " while dispatching to "
                        + msg.target.getClass().getName() + " "
                        + msg.callback + " what=" + msg.what);
            }

            msg.recycle();
        }
}

复制代码

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

直接拿到该looper实例中的消息队列,而后循环每个message(进入了无限循环),遍历消息以后会经过这个message的handler进行分发。

msg.target.dispatchMessage(msg); 中的target是handler

总结looper的主要做用

1) 与当前线程绑定,保证一个线程只会有一个Looper实例,同时一个Looper实例也只有一个MessageQueue。
2) loop()方法,不断从MessageQueue中去取消息,交给消息的target属性的dispatchMessage去处理。

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;
    }

复制代码

handler绑定到looper上,因为一个looper对一个一个消息队列,这样这个handler就绑定到这个looper上了,也同时绑定到了这个线程上。

handler.sendMessgae()是用来说Message添加进消息队列的。。dispatchmessage才是用于分发的(如上looper介绍)

复制代码

public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

复制代码

public void handleMessage(Message msg) {
    }

handleMessage此时是空的函数,须要咱们以后的复写

步骤:

复制代码

一、首先Looper.prepare()在本线程中保存一个Looper实例,而后该实例中保存一个MessageQueue对象;由于Looper.prepare()在一个线程中只能调用一次,因此MessageQueue在一个线程中只会存在一个。

二、Looper.loop()会让当前线程进入一个无限循环,不端从MessageQueue的实例中读取消息,而后回调msg.target.dispatchMessage(msg)方法。

三、Handler的构造方法,会首先获得当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue想关联。

四、Handler的sendMessage方法,会给msg的target赋值为handler自身,而后加入MessageQueue中。

五、在构造Handler实例时,咱们会重写handleMessage方法,也就是msg.target.dispatchMessage(msg)最终调用的方法。

六、handler也能够进行存在于子线程中,为何咱们通常见到的都在主线程中呢?由于通常是针对UI空间更新的操做是不安全的因此handler放在主线程中,若是不存在这样的业务,固然能够用handler
相关文章
相关标签/搜索