Handler MessageQueue Looper

Only the original thread that created a view hierarchy can touch its views


activity/service启动时,会启动三个线程。一个主线程和两个Binder线程

主线程在ActivityThread的main方法中启动,会调用

Looper.prepareMainLooper();方法

在该方法中会调用

sMainLooper = myLooper();

给sMainLooper赋值,与当前主线程进行绑定



public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
        SamplingProfilerIntegration.start();
        // CloseGuard defaults to true and can be quite spammy.  We
        // disable it here, but selectively enable it later (via
        // StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);
        Environment.initForCurrentUser();
        // Set the reporter for event logging in libcore
        EventLogger.setReporter(new EventLoggingReporter());
        AndroidKeyStoreProvider.install();
        // Make sure TrustedCertificateStore looks in the right place for CA certificates
        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
        TrustedCertificateStore.setDefaultUserDirectory(configDir);
        Process.setArgV0("<pre-initialized>");
        Looper.prepareMainLooper();
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }
        // End of event ActivityThreadMain.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }







public static void prepare() {

    prepare(true);

}


private static void prepare(boolean quitAllowed) {

    if (sThreadLocal.get() != null) {

        throw new RuntimeException("Only one Looper may be created per thread");

    }

    sThreadLocal.set(new Looper(quitAllowed));   //创建出Looper对象,并于当前线程进行绑定,set进ThreadLocal中

}



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.recycleUnchecked();

    }

}

app启动后调用Lopper类中的looper方法

通过MyLooper()创建当前线程(app启动时默认主线程,以后是Looper对象所在线程)的looper对象

创建MessageQueue对象,与Looper类中MessageQueue成员变量共享同一内存空间,me.mQueue被改变时,MessageQueue对象随之改变

创建死循环,不断的从MessageQueue队列中取出message对象,为空则阻塞

通过msg.target.dispatchMessage(msg)进行消息的分发,调用该msg所在handler对象的handleMessage方法(target在message入队时已被赋值:Handler类的enqueueMessage()方法中完成target赋值)

整个过程都是在主线程中完成的,所以说子线程如果要创建自己的Looper对象,则需要在自线程中调用loop()方法

 

子线程给主线程子线程给子线程传递数据

Handler中传入的Looper与哪个线程进行绑定,消息就传入哪个线程中进行处理

eg:

Looper.getMainLooper()获得的Looper对象与主线程进行绑定,可以在子线程中sendMessage,handlerMessage()所处线程是主线程

Looper.prepare()获得与当前线程绑定的Looper对象,

如果是在主线程中,则与Looper.getMainLooper()一致。

如果是在子线程中,则是与子线程进行通信(子与子通信),最后还需调用Looper.loop()进行创建该线程的Looper对象。                    

Looper.myLooper()可以获得该Looper对象。如果直不执行Looper.prepare()而直接执行Looper.myLooper()则会空指针异常。



Looper不断获取MessageQueue中的一个Message,然后由Handler来处理。


中央处理器(Looper)从内存(MessageQueue)中取出指令(Message),执行指令(Handler).


一.每个Thread只对应一个Looper

二.每个Looper只对应一个MessageQueue

三.每个MessageQueue中对应n个Message

四.每个Message中最多指定一个Handler来处理事件(多个Message可以指定同一个Handler处理)

所以  

一个Thread对应多个Handler

handler得两个功能

一.处理Message

具体方法:

1.public void dispatchMessage(Message msg)

2.public void handleMessage(Message msg)

Looper从MessageQueue中取出一个Message后,首先会调用Handler.dispatchMessage进行消息派发

然后调用handlerMessage来进行处理


二.将某个Message压入MessageQueue中

具体方法:

1.Post系列

post(Runnable r)

        postAtTime(Runnable r,long uptimeMillis)


2.Send系列

        sendEmptyMessage(int what)

        sendMessageDelayed

        sendMessageAtFrontofQueue

        sendMessageAtTime

 Handler MessageQueue Looper_第1张图片

区别:

post需要把Runnable先包装成一个Message   然后再发送。


Handler-->MessageQueue-->Message-->Handler

这体现了程序设计的有序性


eg:健身房事件,你正在健身房跑步,朋友找你借钱

两种处理方式

1.停止健身,借钱给他

2.秘书加入事件处理队列,按优先级等你健身完毕再交给你处理

如果健身一小时100万,朋友借钱100,你就没必要马上处理。

 



======================

 

 程序中使用Looper有两种情况

一.主线程中使用


二.

 

 

 

 

你可能感兴趣的:(Handler MessageQueue Looper)