Android Handler原理全解析

本文详细剖析了Android Handler的工作原理,从主线程和子线程的创建Handler到Looper的内部机制,包括Looper.prepare()、Looper.loop()以及MessageQueue的相关操作。讲解了消息发送的源码分析,涉及postDelayed()、enqueueMessage()以及epoll在消息队列中的应用。同时,提到了clearCallingIdentity在Binder调用中的作用,以及IntentService和进程间消息传递的实现。提供了相关源码的阅读链接,帮助读者深入理解Android消息处理系统。
摘要由CSDN通过智能技术生成

一.Handler 运行原理图

Handler-8974640

二.创建

1.主线程中创建

一般在 Activity 中这样创建 Handler,其实当前的 Handler 获取的 Looper 是在 ActivityThread 中创建的。

Handler handler = new Handler();//Looper 是在ActivityThread 中创建的

ActivityThread 源码,ActivityThread 并不是一个 Thread ,它只是叫 ActivityThread 来表示它是 Activity 的开始类。

//ActivityThread.java
final H mH = new H();//真正来处理 Message 信息
final Looper mLooper = Looper.myLooper();//当ActivityThread创建的时候,就获得了 Looper
public static void main(String[] args) {
   
    //...code
    Looper.prepareMainLooper();//开启 Looper 的主循环 sThreadLocal.set(new Looper(quitAllowed));
    //...code
    ActivityThread thread = new ActivityThread();
   	//...code
    Looper.loop();//开启循环
}

2.子线程中创建

如果在其他线程想要开启一个 handler ,下面的代码直接运行的话,就会报错。

//handler 在子线程中创建
Thread thread = new Thread(new Runnable() {
   
    @Override
    public void run() {
   
        Handler handler = new Handler();
    }
});

image-20200110172340644

报错提示:如果要在其他线程创建就必须调用 Looper.prepare()Looper.loop()

  • Looper.prepare() 在当前线程创建Looper 对象
  • Looper.loop() 开启循环,保证此线程一直存活
//handler 在子线程中创建
Thread thread = new Thread(new Runnable() {
   
    @Override
    public void run() {
   
        Looper.prepare();
        Handler handler = new Handler();
        Looper.loop();
    }
});

3.Looper分析

3.1). Looper.perpare()
public static void prepare() {
   
    prepare(true);//创建一个可以退出的 Looper 对象
}
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 对象
}
3.2). Looper.loop()

Looper.loop

public static void loop() {
   
    final Looper me = myLooper();//通过 sThreadLocal.get();得到具体的Looper
    if (me == null) {
   //如果 looper 为空 ,那么直接报错
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }
    final MessageQueue queue = me.mQueue;

    Binder.clearCallingIdentity();//清除Binder中的调用 sid,并获取当前的 pid, 让IPCThread 知道 pid 
    final long ident = Binder.clearCallingIdentity();//清除Binder中的调用 sid,并获取当前的 pid, 让IPCThread 知道 pid 
    //... 
    for (;;) {
   
        Message msg = queue.next(); // 取出消息,可能会中断
        if (msg == null) {
   
            //没有消息,则退出循环
            return;
        }
        //...
        try {
   
            msg.target.dispatchMessage(msg);//真正执行 Runnable()中的 run() 或者 handleMessage()
            //执行 和 msg 相关联 handler 的 dispatchMessage() 方法
          	//请看下面的代码分析
        } catch (Exception exception) {
     
        } finally {
   
        }
        //...
        final long newIdent = Binder.clearCallingIdentity();//清除Binder中的调用 sid,并获取当前的 pid, 让IPCThread 知道 pid 
        //...
        msg.recycleUnchecked();//消息回收
    }
}

msg.target.dispatchMessage(msg) 源码分析

我们看Message类,里面保存了当前绑定的 HandlerRunnablenextMessage 等重要的元素。

//Message.java
public final class Message implements Parcelable {
   
    /*package*/ Handler target;//关联的具体的 Handler 对象

    /*package*/ Runnable callback;//如果使用的 post(Runnable r); 方法的都会吧 Runable

    /*package*/ android.os.Message next;//单链表,指向下一个消息
}

我们从 post()方法看

//Handler.java    
//发送消息
public final boolean post(@NonNull Runnable r) {
   
    return sendMessageDelayed(getPostMessage(r), 0);
}
//把具体的 Runnable 绑定到 Message.callback 上
private static Message getPostMessage(Runnable r) {
   
    Message m = Message.obtain();
    m.callback = r;
    return m;
}

//Handler.java    
public void dispatchMessage(@NonNull Message msg) {
   
    if (msg.callback != null) {
   //
        handleCallback(msg);//执行绑定的 Runnable callback
    } else {
   
        if (mCallback != null) {
   // Handler 构造方法传入 public Handler(Callback callback, boolean async);
            if (mCallback.handleMessage(msg)) {
   //
                return;
            }
        }
        handleMessage(msg);//执行 Handler 的 handleMessage()方法
    }
}
3.3).MessageQueue.next()
Message next() {
   
    final long ptr = mPtr;
    if (ptr == 0) {
   
        return null;
    }
    //...
    for (;;) {
   
        //...
        nativePollOnce(ptr, nextPollTimeoutMillis);//没有任务就挂起 nextPollTimeoutMillis:-1 表示永久阻塞
        synchronized (this) {
   
            final long now = SystemClock.uptimeMillis();
            Message prevMsg = null;
            Message msg = mMessages;
            if (msg != null && msg.target == null) {
   //取出异步消息
              	//被障碍物挡住了。查找队列中的第一个异步消息。
                do {
   
                    prevMsg = msg;
                    msg = msg.next;
                } while (msg != null && !msg.isAsynchronous()); 
              	//如果为isAsynchronous()=true  :while(true&&false)=> false 已经获取到异步消息
              	//如果为isAsynchronous()=false :while(true&&true) => true 继续循环获取异步消息
              	//总结:先会执行异步消息,然后才执行正常消息。
            }
            if (msg != null) {
   
                if (now < msg.when) {
   //时间点内没有任务,计算下次要执行的之间
                    nextPollTimeoutMillis = 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值