字节跳动:必面题说一下Android消息机制,android音视频编解码

  • Note that Parcelable objects here are not supported prior to

  • the {@link android.os.Build.VERSION_CODES#FROYO} release.

*/

public Object obj;

  1. Message的创建方式:虽然Message有公有构造函数,但是建议使用其提供的obtain系列函数来获取Message对象,这种创建方式会重复利用缓存池中的对象而不是直接创建新的对象,从而避免在内存中创建太多对象,避免可能的性能问题。

/**

  • Return a new Message instance from the global pool. Allows us to

  • avoid allocating new objects in many cases.

*/

public static Message obtain() {

synchronized (sPoolSync) {

// 缓存池中存在可用对象时去缓存池获取 Message 对象。

if (sPool != null) {

// 获取缓存中的对象,并把缓存池指针后移。

Message m = sPool;

sPool = m.next;

m.next = null;

// 清除标志位

m.flags = 0; // clear in-use flag

// 更新当前缓存池大小

sPoolSize–;

return m;

}

}

// 缓存池中没有可用对象时直接创建一个新的 Message 对象。

return new Message();

}

Message中有一系列obtain函数用以在不同场景中获取对象,但这个是最核心的,其他函数都会在其内部调用它,有兴趣的同学可以自行查看源码,考虑到篇幅问题,这里就不再一一列举说明了。

看到这里,相信大家都会有一个疑问:obtain函数是从缓存池中获取Message对象,那缓存池中的对象是什么时候被添加进去的呢?既然缓存池中的对象都是一些可以被重复使用的对象,很明显是在Message对象不再被需要的时候,即从MessageQueue中取出并分发给Handler的时候,被添加到缓存中的,使用的是recycleUnchecked函数:

/**

  • Recycles a Message that may be in-use.

  • Used internally by the MessageQueue and Looper when disposing of queued Messages.

*/

void recycleUnchecked() {

// 设置标志位为“使用中”,在从缓存中取出时会清除这个标志位。

flags = FLAG_IN_USE;

// Message 对象中的信息都不再有意义,在放入缓存池前直接清空。

what = 0;

arg1 = 0;

arg2 = 0;

obj = null;

replyTo = null;

sendingUid = -1;

when = 0;

target = null;

callback = null;

data = null;

synchronized (sPoolSync) {

// 缓存池中只缓存一定数量的 Message 对象,默认是 50 个。

if (sPoolSize < MAX_POOL_SIZE) {

// 把对象放在缓存池的链表首部。

next = sPool;

sPool = this;

// 及时更新缓存池大小。

sPoolSize++;

}

}

}

3.2 创建消息队列

消息队列的创建对消息传递至关重要,它决定了消息在传递过程中的存取方式。但是线程在默认情况下是没有消息队列的,也无法在其内部进行消息循环。如果想为线程开启消息循环就需要使用到Looper类,它可以为关联的线程创建消息队列并开启消息循环,创建消息队列的方式是调用prepare()接口:

/**

  • 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.

*/

public final class Looper {

// 省略无关代码

// sThreadLocal.get() will return null unless you’ve called prepare().

static final ThreadLocal sThreadLocal = new ThreadLocal();

// 内部的消息队列和关联的线程

final MessageQueue mQueue;

final Thread mThread;

// 省略无关代码

/** Initialize the current thread as a looper.

  • This gives you a chance to create handlers that then re

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值