Looper源码分析

一、为什么Handler可以在主线程中直接可以使用呢?

因为主线程(UI线程)的Looper在应用程序开启时创建好了,即在ActivityThread.main方法中创建的,ActivityThread.main函数为Android应用程序的入口

public static void main(String[] args) {
	...
    Process.setArgV0("");
	// 1. 创建消息循环Looper
    Looper.prepareMainLooper();

    ActivityThread thread = new ActivityThread();
    thread.attach(false);

    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
	...
	//2. 执行消息循环
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}
Looper中最为重要的两个方法:
  • Looper.prepareMainLooper():该方法是Looper对象的初始化
  • Looper.loop():该方法会循环取出Message Queue的Message将取出的Message交付给相应的Handler(Looper的作用就体现在这里)

二、Looper.prepareMainLooper()

//在主线程中初始化Looper
public static void prepareMainLooper() {
	//在这里会调用prepare(boolean quitAllowed)方法
    prepare(false);
    synchronized (Looper.class) {
        if (sMainLooper != null) {
            throw new IllegalStateException("The main Looper has already been prepared.");
        }
        sMainLooper = myLooper();
    }
}

//看下prepare(boolean quitAllowed)方法
private static void prepare(boolean quitAllowed) {
	//判断sThreadLocal是否为null,否则抛出异常
	//即Looper.prepare()方法不能被调用两次
	//也就是说,一个线程中只能对应一个Looper实例
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    //初始化Looper对象设置到ThreadLocal中
    sThreadLocal.set(new Looper(quitAllowed));
}

//看下Looper的构造方法
private Looper(boolean quitAllowed) {
	//创建了一个MessageQueue(消息队列)
	//这说明,当创建一个Looper实例时,会自动创建一个与之配对的MessageQueue(消息队列)
    mQueue = new MessageQueue(quitAllowed);
    mThread = Thread.currentThread();
}
整个Looper的初始化准备工作就完了,这里做了哪几件事:
  • Looper的创建会关联一个MessageQueen的创建
  • Looper对象只能被创建一次
  • Looper对象创建后被存放在sThreadLocal

三、Looper.loop()

public static void loop() {
	//myLooper()方法作用是返回sThreadLocal存储的Looper实例,如果me为null,loop()则抛出异常
	//也就是说loop方法的执行必须在prepare方法之后运行
	//也就是说,消息循环必须要先在线程当中创建Looper实例
    final Looper me = myLooper();
    if (me == null) {
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }
	//获取looper实例中的mQueue(消息队列)
    final MessageQueue queue = me.mQueue;

    Binder.clearCallingIdentity();
    final long ident = Binder.clearCallingIdentity();
	//进入消息循环
    for (;;) {
	    //next()方法用于取出消息队列里的消息
		//如果取出的消息为空,则线程阻塞
        Message msg = queue.next(); 
        if (msg == null) {
            
            return;
        }

        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.traceBegin(traceTag, msg.target.getTraceName(msg));
        }
        try {
	        //消息派发:把消息派发给msg的target属性,然后用dispatchMessage方法去处理
			//Msg的target其实就是handler对象,下面会继续分析
            msg.target.dispatchMessage(msg);
        } finally {
            if (traceTag != 0) {
                Trace.traceEnd(traceTag);
            }
        }

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

        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();
    }
}
整个Looper的循环过程就完了,这里做了哪几件事:
  • 取出Looper和MessageQueen
  • 进入消息循环,有消息则分发出去
  • 消息资源的回收

四、Looper的退出

Looper也提供了两个方法可以退出一个Looper:
  • quit():quit会直接退出Looper
  • quitSafety():quitSafety只是设定一个退出标记,然后把消息队列中的已有消息处理完毕后退出Looper

你可能感兴趣的:(Android,Looper,Android源码分析)