欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android基础之Handler机制(四)Looper源码分析

程序员文章站 2022-03-08 11:56:53
...

基于8.0.0源码

##定义##

 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 {@link #prepare} in the thread that is to run the loop, and then {@link #loop} to have it process messages until the loop is stopped.

个人理解

- Looper的作用是不断的从MessageQueue中取出消息传给宿主Handler来处理. 主线程不需要我们做操作,系统已经做好处理.
- 如果是新建一个线程需要使用Looper的话, 需要先调用prepare()方法来初始化Looper,然后调用loop()方法来开启循环.

方法细节

构造方法

  • 我们可以看到构造方法是私有的,就是不允许通过构造来创建.

      private Looper(boolean quitAllowed) {
      	//创建MessageQueue队列
      	mQueue = new MessageQueue(quitAllowed);
      	//得到当前的线程
      	mThread = Thread.currentThread();
      }
    
  • 一个线程只能有一个Looper实例

初始化方法

  • 不能通过构造方法来创建对象,那我们看系统提供了哪些方法

  • static void prepare()

      //在子线程中使用Looper的时候调用
     	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");
      	}
      	//创建Looper
      	sThreadLocal.set(new Looper(quitAllowed));
      }
    
  • static void prepareMainLooper()

      //主线程即UI线程开启的时候系统已经创建了主线程的Looper,这里不需要我们去调用这个方法
       public static void prepareMainLooper() {
      	prepare(false);
      	synchronized (Looper.class) {
          	if (sMainLooper != null) {
              	throw new IllegalStateException("The main Looper has already been prepared.");
          	}
          	sMainLooper = myLooper();
      	}
      }
    

工作线程获取Looper以及MessageQueue###

//返回当前工作线程的looper,如果当前线程没有初始化looper则会返回空
public static @Nullable Looper myLooper() {
    return sThreadLocal.get();
}

//返回当前线程正在运行的looper创建的MessageQueue,否则会抛出空指针异常
public static @NonNull MessageQueue myQueue() {
    return myLooper().mQueue;
}

loop 方法

  • Looper就是通过此方法不停的从MessageQueue中取出Msg,然后再传递给宿主Handler来处理

      public static void loop() {
      //得到当前线程的looper
      final Looper me = myLooper();
      //looper没有初始化,抛出异常
      if (me == null) {
          throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
      }
      //得到当前线程的MessageQueue
      final MessageQueue queue = me.mQueue;
    
      //得到当前线程的唯一标识 
      final long ident = Binder.clearCallingIdentity();
      
      for (;;) {
      	//取出队列中消息
          Message msg = queue.next();
          if (msg == null) {
              // No message indicates that the message queue is quitting.
              return;
          }
    
      	....
          try {
      		//把消息分发给Handler,Handler来处理消磁
              msg.target.dispatchMessage(msg);
              end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
          } finally {
              if (traceTag != 0) {
                  Trace.traceEnd(traceTag);
              }
          }
          ....
      	//消息被回收
          msg.recycleUnchecked();
      }
    

    }