Android消息机制底层原理

本文深入探讨Android消息机制,涵盖ThreadLocal线程局部变量的存储、set、get方法,MessageQueue的enqueueMessage和next操作,Message实体,Looper的消息循环,Handle的创建、发送和接收过程,以及主线程的消息循环机制。同时,分析了runOnUiThread如何利用Handler和mainLooper在UI线程中执行任务。
摘要由CSDN通过智能技术生成

1.概述

Android的消息机制主要是指Handler的运行机制,Handler的运行需要底层的MessageQueue和Looper的支撑。MessageQueue是消息队列。他的内存存储了一组消息,以队列的形式对外提供插入和删除的工作。他的内部存储结构并不是真正的队列,而是采用单链表的数据结构来存储消息列表。Looper为消息循环,由于MessageQueue只是一个消息的存储单元,它不能去处理消息,而Looper就填补了这个功能,Looper会以无限循环的形式去查找是否有新的消息,如果有的话就处理消息,否则就一直等待,Looper还有一个特殊的概念,那就是ThreadLocal,ThreadLocal并不是线程,它的作用可以在每个线程中存储数据。我们知道,Handler创建的时候会采用当前线程的Looper来构造消息循环系统,那么Handler内部如何获取到当前线程的Looper呢?这就要使用ThreadLocal了,ThreadLocal可以在不同的线程中互不干扰地存储并提供数据,通过ThreadLocal可以轻松获取每个线程的Looper。当然需要注意的是,线程是默认没有Looper的,如果需要使用Handler就必须为线程创建Looper。我们经常提到的主线程,也就是UI线程,它就是ActivityThread,ActivityThread被创建时会初始化Looper,这也是在主线程中默认可以使用Handler的原因。

2.ThreadLocal-线程局部变量

ThreadLocal是一个现场内部的数据存储类,通过它可以在指定的线程中存储数据,数据存储以后,只有在指定线程中可以获取到存储的数据。对于Handler来说,它需要获取当前线程的Looper,很显然Looper的作用域就是线程并且不同线程具有不同的Looper,这个时候通过ThreadLocal就可以轻松实现Looper在线程中的存储。ThreadLocal是一个泛型类。

1)存储机制

在localValues内部有一个数组;private Object[]table,ThreadLocal的值就存在这个table数组中,ThreadLocal的值在table数组中的存储位置总是为ThreadLocal的reference字段所标识的对象的下一个位置,比如ThreadLocal的reference对象在table数组中的索引为index,那么ThreadLocal的值在table数组中的索引就是index+1.最终ThreadLocal的值将会被存储在table数组中:table[index+1]=value
//value加入数据
 void put(ThreadLocal<?> key, Object value) {
  cleanUp();

  // Keep track of first tombstone. That's where we want to go back
  // and add an entry if necessary.
  int firstTombstone = -1;

  for (int index = key.hash & mask;; index = next(index)) {
  Object k = table[index];

  if (k == key.reference) {
  // Replace existing entry.
  table[index + 1] = value;
  return;
  }

  if (k == null) {
  if (firstTombstone == -1) {
  // Fill in null slot.
  table[index] = key.reference;
  table[index + 1] = value;
  size++;
  return;
  }

  // Go back and replace first tombstone.
  table[firstTombstone] = key.reference;
  table[firstTombstone + 1] = value;
  tombstones--;
  size++;
  return;
  }

  // Remember first tombstone.
  if (firstTombstone == -1 && k == TOMBSTONE) {
  firstTombstone = index;
  }
  }
  }

//获取当前线程的数据
  Values values(Thread current) {
  return current.localValues;//当前线程存储的数组
  }

//初始化当前线程的数据
Values initializeValues(Thread current) {
  return current.localValues = new Values();
  }

2)set

  public void set(T value) {
  Thread currentThread = Thread.currentThread();//获取当前的线程
  Values values = values(currentThread);//
  if (values == null) {
  values = initializeValues(currentThread);
  }
  values.put(this, value);
  }

3)get

 public T get() {
  // Optimized for the fast path.
  Thread currentThread = Thread.currentThread();
  Values values = values(currentThread);
  if (values != null) {
  Object[] table = values.table;
  int index = hash & values.mask;
  if (this.reference == table[index]) {
  return (T) table[index + 1];
  }
  } else {
  values = initializeValues(currentThread);
  }

  return (T) values.getAfterMiss(this);
  }


从ThreadLocal的set和get方法
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值