「带着问题看Handler」

本文深入探讨了Android中Handler、MessageQueue和Looper的工作原理,分析了它们在单线程模型下的角色。针对常见问题,如一个线程的Handler、Looper、MessageQueue数量,消息创建,内存泄漏,线程安全等进行了详细解答。文章通过源码分析揭示了Handler如何发送和处理消息,MessageQueue如何存储和分发消息,以及Looper如何维持消息循环。同时,指出了在子线程中使用Looper和Handler进行线程切换的机制。最后,讨论了性能优化、设计思想以及Android开发的相关知识,包括Git、Gradle、自动化测试等。
摘要由CSDN通过智能技术生成
一、写在前面

Android系统在设计之初被设计成单线程模型,其实不仅仅是Android,像Java Swing都使用了单线程模型,这也是有历史原因的。回到Android中,都知道只能在UI线程也即主线程中更新UI,并且规定了UI线程中不能够进行耗时操作(5S),像网络请求,I/O操作等。否则会出现ANR,程序无响应。作为开发这是最不愿意看的。那么实际开发中肯定也会有需要在子线程更新UI的场景,可以说Handler也是为了解决这一矛盾的-只能在UI线程中更新UI。官方注释中同样给出了Handler两大主要作用:

1.To schedule messages and runnables to be executed at some point in the future;

2.To enqueue an action to be performed on a different thread than your own.

二、带着问题看

Android上线源码阅读工具(Android Code Search)后查看源码相比于之前算是极大的方便了,可以看到最新版本的源码信息,同样也支持调用之间的跳转;几乎跟Android Studio相差无几了。如图,可以根据需要选择想要查看的源码版本:

Android_code.png

就自身而言,无论是Android的系统源码还是其他优秀开源库的源码的阅读,在准备阅读之前都会整理出自己想要了解的方向或者问题,这样带着问题去看,优先看与问题相关的内容。个人认识还是比较高效的,毕竟系统源码设计细节太过于复杂,深陷细节当中往往达不到整体把握的效果。那么常见的问题或者说作为上层App开发应该需要掌握哪些内用与细节呢?

三、常见问题

1.一个线程有几个Handler?

2.一个线程有几个Looper?如何保证?

3.一个线程可以有几个MessageQueue?

4.如何创建一个Message对象?

5.Handler内存泄漏的根本原因?内部类是不是都会导致内存泄漏?

6.主线程中如何实例化一个Handler对象,子线程中呢?

7.Looper死循环为什么不会导致应用ANR,会消耗资源吗?

8.子线程中维护Looper,消息队列无消息时如何处理?有什么用?

9.使用Handler的postDelay后消息队列的变化?

10.多个Handler如何保证线程安全?

11.什么是同步屏障,有什么作用,同步屏障与异步消息的具体使用场景?

12.Android IdleHandler应用场景?

13.可以多次创建Looper对象嘛?

14.MessageQueue作用,数据结构?

15.延迟消息的实现?

16.pipe/epoll机制?

简单的总结了一些需要掌握的问题,带着这些问题看源码的具体实现,做到心中有数。当然重点还是要关注HandlerMessageLooper这套机制的具体实现细节。基于源码Android-12.0.0_r4

1.Handler具体实现

消息的的处理类,主要的职责是发送消息到“消息队列”,并处理消息。

  • 构造函数:
@Deprecated
public Handler() {
  this(null, false);
}

@Deprecated
public Handler(@Nullable Callback callback) {
  this(callback, fasle);
}

public Handler(@NonNull Looper looper) {
  this(looper, null, false);
}

public Handler(@NonNull Looper looper, @Nullable Callback callback) {
  this(looper, callback, false);
}

@UnsupportedAppUsage
public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
  mLooper = looper;
  mQueue = looper.mQueue;
  mCallback = callback;
  mAsynchronous = async;
}
//..... 

在最新的源码之中,关于构造函数中不带Looper参数的方法已经被打上**@Deprecated的标签,官方已经不建议这样实例化出一个Handler**对象(隐式的指定Looper对象),源码给出的解释:

Implicitly choosing a Looper during Handler construction can lead to bugs where operations are silently lost (if the Handler is not expecting new tasks and quits) crashes .

先不具体深究,继续往下看Handler其他比较重要的方法有哪些。

  • 方法处理handleMessage()
//Subclasses must implement this to receive messages.
public void handleMessage(@NonNull Message msg) {
  //空方法,实现类需要处理用来接收信息
}
//Callback interface you can use when instantiating a Handler to avoid 
//having to implement your own subclass of Handler.
public interface Callback {
  boolean handleMessage(@NonNull Message msg);
} 

方法处理比较简单,一个Callback接口,当然可以在实例化Handler的作为参数传入,同时包含一个handleMessage的空方法,需要子类自己实现具体的消息处理细节。

  • 消息的分发
//Handle system messages here.
public void dispatchMessage(@NonNull Message msg) {
  if (msg.callback != null) {
      handleCallback(msg);
  } else {
      if (mCallback != null) {
         if (mCallback.handleMessage(msg)) {
             return;
         }
       }
    handleMessage(msg);
  }
}

public final boolean post(@NonNull Runnable r) {
  return  sendMessageDelayed(getPostMessage(r), 0);
}
public final boolean postAtTime(@NonNull Runnable r, long uptimeMillis) {
  return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}
public final boolean postAtTime(@NonNull Runnable r, @Nullable Object token, long uptimeMillis) {
  return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
}
public final boolean postDelayed(@NonNull Runnable r, long delayMillis) {
  return sendMessageDelayed(getPostMessage(r), delayMillis);
}
//@hide
public final boolean postDelayed(Runnable r, int what, long delayMillis) {
  return sendMessageDelayed(getPostMessage(r).setWhat(what), delayMillis);
}

public final boolean sendMessage(@NonNull Message msg) {
  return sendMessageDelayed(msg, 0);
}
public final boolean sendEmptyMessage(int what) {
  return sendEmptyMessageDelayed(what, 0);
}
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
   Message msg = Message.obtain();
   msg.what = what;
   return sendMessageDelayed(msg, delayMillis);
}
public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
   Message msg = Message.obtain();
   msg.what = what;
   return sendMessageAtTime(msg, uptimeMillis);
}

public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
   if (delayMillis < 0) {
      delayMillis = 0;
   }
   return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}

public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
   MessageQueue queue = mQueue;
   if (queue == null) {
       RuntimeException e = new RuntimeException(
       this + " sendMessageAtTime() called with no mQueue");
       Log.w("Looper", e.getMessage(), e);
       return false;
    }
    return enqueueMessage(queue, msg, uptimeMillis);
 }

private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
    long uptimeMillis) {
    msg.target = this;
    msg.workSourceUid = ThreadLocalWorkSource.getUid();
    if (mAsynchronous) {
       msg.setAsynchronous(true);
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值