Looper判断当前线程是否是主线程

来源:互联网 发布:pc安装mac os x 10.11 编辑:程序博客网 时间:2024/06/07 02:47

1.判断方法

可以借助Looper来判断当前线程是否是主线程:

代码:

public boolean isMainThread() {    return Looper.getMainLooper() == Looper.myLooper();}

这里写图片描述

这里写图片描述

getMainLooper()得到的是整个application的主线程。myLooper()得到的是当前线程。

2.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, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.

官方推荐使用例子:

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

2.1.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.classfinal MessageQueue mQueue;final Thread mThread;private Printer mLogging;private long mTraceTag;

sThreadLocal每个使用该变量的线程都会将已创建的Looper存储到其中,并在prepare的时候调用判断,是否已经创建过Looper

2.2.prepare

public static void prepare() {    prepare(true);}private static void prepare(boolean quitAllowed) {    if (sThreadLocal.get() != null) {//每个线程只能有一个looper        throw new RuntimeException("Only one Looper may be created per thread");    }    sThreadLocal.set(new Looper(quitAllowed));}

2.3.构造方法

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

创建了消息队列并绑定了当前线程

2.4.loop方法

public static void loop() {    final Looper me = myLooper(); //返回当前线程绑定的looper    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        final Printer logging = me.mLogging;        if (logging != null) {            logging.println(">>>>> Dispatching to " + msg.target + " " +                    msg.callback + ": " + msg.what);        }        final long traceTag = me.mTraceTag;        if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {            Trace.traceBegin(traceTag, msg.target.getTraceName(msg));        }        try {//有消息就分发            msg.target.dispatchMessage(msg);        } finally {            if (traceTag != 0) {                Trace.traceEnd(traceTag);            }        }        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();    }}

首先调用myLooper方法获取当前looper:

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

接着拿到该looper对应的消息队列me.mQueue。然后就无限循环从队列里取消息Message,取到消息后就调用msg.target.dispatchMessage(msg)方法进行消息处理。

消息处理完之后要进行回收,msg.recycleUnchecked()

3.总结

一个线程对应一个Looper,一个Looper对应一个MessageQueue,Looper调用loop()开始通过消息队列的next()方法来无限循环获取消息并处理。

阅读全文
0 0