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

Android源码分析之Handler机制

程序员文章站 2022-07-14 19:40:45
...

面试的时候经常被问到Handler机制,但一直也没有自己去看源码总结,最近有空,自己总结下。自我感觉逻辑方面很清晰。

Handler机制本质上就是一个MessageQueue管理Message的过程

先上图

Looper.prepare初始化looper
looper内部初始化
cpp中回调
自己写的逻辑 把message压入队列
Looper.loop运行消息队列
handleMessage
创建Handler
配置Looper
消息队列
创建发送消息的Thread
回调run方法
looper循环

分析具体步骤:

  1. 创建Handler
  2. 初始化looper
  3. 开启循环遍历消息队列
  4. 创建Thread 并设置回调
  5. 回调Thread的run方法
  6. 发送消息

1. 创建Handler

默认情况下,会获取当前线程的looper,如果非主线程没有初始化,会抛异常

		mLooper = Looper.myLooper();
		if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
        }

2. 初始化looper Looper.prepare()

初始化looper,会通过cpp建立一个消息队列,并且looper中持有当前线程的对象

	private static void prepare(boolean quitAllowed) {
        ...
        sThreadLocal.set(new Looper(quitAllowed));
    }
    private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);//looper绑定消息队列
        mThread = Thread.currentThread();//looper绑定当前线程
    }
    MessageQueue(boolean quitAllowed) {
        mQuitAllowed = quitAllowed;
        mPtr = nativeInit();//创建对应的cpp   NativeMessageQueue*对象
    }

3. 开启循环遍历消息队列 looper.looper()

开启一个死循环来遍历消息队列

 //looper方法中执行死循环
 for (;;) {
 	...
 	//looper()方法中
	msg.target.dispatchMessage(msg);
 }
 //handler()方法中
 public void dispatchMessage(Message msg) {
     ...
     //调用自定义逻辑
     handleMessage(msg);
 }	

4. 创建Thread pthread_create创建线程,并设置回调

//cpp中创建
Thread* child_thread = new Thread(is_daemon);
//创建线程
pthread_create_result = pthread_create(&new_pthread,&attr,Thread::CreateCallback,child_thread);

5. 通过java_lang_Thread_run调用Thread的run方法

//回调java
jmethodID mid = WellKnownClasses::java_lang_Thread_run;
...
InvokeVirtualOrInterfaceWithJValues(soa, ref.get(), mid, nullptr);
...
ArtMethod* method = FindVirtualMethod(receiver, jni::DecodeArtMethod(mid));
...
InvokeWithArgArray(soa, method, &arg_array, &result, shorty);

6. 发送消息handler.sendEmptyMessage(1)

//获取looper的消息队列
MessageQueue queue = mQueue;
//消息msg插入队列中
msg.next = p; 
prev.next = msg;