| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> Android PooledLambda记录 -> 正文阅读 |
|
[移动开发]Android PooledLambda记录 |
首先需要弄清楚Pool,这个接口的定义位于frameworks/base/core/java/android/util/Pools.java 是一个工具类,内容如下: public static interface Pool<T> { /** * @return An instance from the pool if such, null otherwise. */ @UnsupportedAppUsage public T acquire(); /** * Release an instance to the pool. * * @param instance The instance to release. * @return Whether the instance was put in the pool. * * @throws IllegalStateException If the instance is already in the pool. */ @UnsupportedAppUsage public boolean release(T instance); } 可以看到只有两个方法,这是一个池子管理的内容方式非常单一就两种,一种是请求,一种是发布。在这个文件中有一个简单的实现,如下: /** * Simple (non-synchronized) pool of objects. * * @param <T> The pooled type. */ public static class SimplePool<T> implements Pool<T> { @UnsupportedAppUsage private final Object[] mPool; private int mPoolSize; /** * Creates a new instance. * * @param maxPoolSize The max pool size. * * @throws IllegalArgumentException If the max pool size is less than zero. */ @UnsupportedAppUsage public SimplePool(int maxPoolSize) { if (maxPoolSize <= 0) { throw new IllegalArgumentException("The max pool size must be > 0"); } mPool = new Object[maxPoolSize]; } @Override @SuppressWarnings("unchecked") @UnsupportedAppUsage public T acquire() { if (mPoolSize > 0) { final int lastPooledIndex = mPoolSize - 1; T instance = (T) mPool[lastPooledIndex]; mPool[lastPooledIndex] = null; mPoolSize--; return instance; } return null; } @Override @UnsupportedAppUsage public boolean release(T instance) { if (isInPool(instance)) { throw new IllegalStateException("Already in the pool!"); } if (mPoolSize < mPool.length) { mPool[mPoolSize] = instance; mPoolSize++; return true; } return false; } private boolean isInPool(T instance) { for (int i = 0; i < mPoolSize; i++) { if (mPool[i] == instance) { return true; } } return false; } } 可以得出,这个类就是用来管理一个对象栈,当aquire的时候就把最后一个实例取出来并且删除,release的时候就检索一下是否存在,存在就不入栈,不存在就放在最后一个,检索这一步就是与栈的唯一区别,然后有一个同步类定义如下: /** * Synchronized pool of objects. * * @param <T> The pooled type. */ public static class SynchronizedPool<T> extends SimplePool<T> { private final Object mLock; /** * Creates a new instance. * * @param maxPoolSize The max pool size. * @param lock an optional custom object to synchronize on * * @throws IllegalArgumentException If the max pool size is less than zero. */ public SynchronizedPool(int maxPoolSize, Object lock) { super(maxPoolSize); mLock = lock; } /** @see #SynchronizedPool(int, Object) */ @UnsupportedAppUsage public SynchronizedPool(int maxPoolSize) { this(maxPoolSize, new Object()); } @Override @UnsupportedAppUsage public T acquire() { synchronized (mLock) { return super.acquire(); } } @Override @UnsupportedAppUsage public boolean release(T element) { synchronized (mLock) { return super.release(element); } } } 只是原有的基础上加锁,防止多线程访问下资源的竞争。 接下来我们先看一个使用实例,如下: mHandler.sendMessage(PooledLambda.obtainMessage( AppOpsService::notifyOpChanged, this, repCbs, code, uid, packageName)); 这里可以看到我们这里直接使用了PooledLambda的obtainMessage函数,这个函数的定义如下: static <A, B, C, D, E> Message obtainMessage( QuintConsumer<? super A, ? super B, ? super C, ? super D, ? super E> function, A arg1, B arg2, C arg3, D arg4, E arg5) { synchronized (Message.sPoolSync) { PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool, function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null, null, null, null); return Message.obtain().setCallback(callback.recycleOnUse()); } } 可以看到这是一个静态函数,可以在接口外部直接被调用,这个接口里面就是使用了我们经典的lambda定义方式。这个泛型的定义巧妙的將我们的函数以及需要传出的参数类型巧妙的连接起来,第一个传入的lambda接口跟后面的参数类型紧紧相关,我们调用这个函数的时候直接將需要传入的参数一并传入,省的后续再次重新传参。这里需要提到的是lambda里面的中间接口是一种隐藏式的存在我们在调用的过程中可以直接匿名忽略掉,本次的调用实例就是如此,直接使用了::符号直接链接到目标函数notifyOpChanged。 这里传入QuintConsumer接口,这个接口的定义如下: public interface QuintConsumer<A, B, C, D, E> { void accept(A a, B b, C c, D d, E e); } 可以看到这个接口只有一个方法,这个方法就是我们要去用lamba来实现的功能。这里需要注意的是我们的accept函数是需要5个参数的,但是我们在调用赋值的 notifyOpChanged函数只有四个参数如下: private void notifyOpChanged(ArraySet<ModeCallback> callbacks, int code, int uid, String packageName) { for (int i = 0; i < callbacks.size(); i++) { final ModeCallback callback = callbacks.valueAt(i); notifyOpChanged(callback, code, uid, packageName); } } 为什么这样被允许,可以看到我们obtainMessage这个函数定义的时候后面是紧跟着5个参数的,我们只需要在调用的时候將第2个参数传入为this这样默认我们4个参数的函数就允许被加载进去,第2个参数相当于是一个指针,指向我们这个函数定义的类。 根据泛型的定义我们可以推测到五个参数分别为this类的类型然后是ModeCallBack,int,int,String的类型。默认我们把this已经作为一个参数传递给QuintConsumer接口。 然后去看acquire函数的定义这个函数位于frameworks/base/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java可以看到这是一个实现类,他就是实现我们PooledLambda里面的一些具体功能。这个类继承自OmniFunction,而QmniFunction是一个抽象类,里面包含了Pooled的所有功能实现,这些实现又全部通过指派给了抽象函数involk,这样具体的实现就交给了子类。可以认为这里就是一个列表,列出了所有要实现的函数。 abstract class OmniFunction<A, B, C, D, E, F, G, H, I, R> implements PooledFunction<A, R>, BiFunction<A, B, R>, TriFunction<A, B, C, R>, QuadFunction<A, B, C, D, R>, QuintFunction<A, B, C, D, E, R>, HexFunction<A, B, C, D, E, F, R>, HeptFunction<A, B, C, D, E, F, G, R>, OctFunction<A, B, C, D, E, F, G, H, R>, NonaFunction<A, B, C, D, E, F, G, H, I, R>, PooledConsumer<A>, BiConsumer<A, B>, TriConsumer<A, B, C>, QuadConsumer<A, B, C, D>, QuintConsumer<A, B, C, D, E>, HexConsumer<A, B, C, D, E, F>, HeptConsumer<A, B, C, D, E, F, G>, OctConsumer<A, B, C, D, E, F, G, H>, NonaConsumer<A, B, C, D, E, F, G, H, I>, PooledPredicate<A>, BiPredicate<A, B>, PooledSupplier<R>, PooledRunnable, ThrowingRunnable, ThrowingSupplier<R>, PooledSupplier.OfInt, PooledSupplier.OfLong, PooledSupplier.OfDouble abstract R invoke(A a, B b, C c, D d, E e, F f, G g, H h, I i); @Override public R apply(A o, B o2) { return invoke(o, o2, null, null, null, null, null, null, null); } 令人眼花缭乱,这样一个工具类包含的功能确实齐全,但是真站内存啊阿。 我们的子类PooledLambdaImpl相当忙活去实现这invoke函数。 我们继续查看PooledLambdaImpl的acquire这个静态函数如下: /** * Internal non-typesafe factory method for {@link PooledLambdaImpl} */ static <E extends PooledLambda> E acquire(Pool pool, Object func, int fNumArgs, int numPlaceholders, int fReturnType, Object a, Object b, Object c, Object d, Object e, Object f, Object g, Object h, Object i) { PooledLambdaImpl r = acquire(pool); if (DEBUG) { Log.i(LOG_TAG, "acquire(this = @" + hashCodeHex(r) + ", func = " + func + ", fNumArgs = " + fNumArgs + ", numPlaceholders = " + numPlaceholders + ", fReturnType = " + LambdaType.ReturnType.toString(fReturnType) + ", a = " + a + ", b = " + b + ", c = " + c + ", d = " + d + ", e = " + e + ", f = " + f + ", g = " + g + ", h = " + h + ", i = " + i + ")"); } r.mFunc = Preconditions.checkNotNull(func); r.setFlags(MASK_FUNC_TYPE, LambdaType.encode(fNumArgs, fReturnType)); r.setFlags(MASK_EXPOSED_AS, LambdaType.encode(numPlaceholders, fReturnType)); if (ArrayUtils.size(r.mArgs) < fNumArgs) r.mArgs = new Object[fNumArgs]; setIfInBounds(r.mArgs, 0, a); setIfInBounds(r.mArgs, 1, b); setIfInBounds(r.mArgs, 2, c); setIfInBounds(r.mArgs, 3, d); setIfInBounds(r.mArgs, 4, e); setIfInBounds(r.mArgs, 5, f); setIfInBounds(r.mArgs, 6, g); setIfInBounds(r.mArgs, 7, h); setIfInBounds(r.mArgs, 8, i); return (E) r; } 通过这里我们可以看到最终返回的是一个r,这个r的类型为PooledLambdaImpl类型,因为这个类型继承了OmniFunction并且OmniFunction实现了那么多接口,所以这个类型所涵盖的范围就很广了,我们此次acquire的PooledRunnable类型只是其中的一种,这里QmniFunction的很巧妙的使用了设计模式中的依赖倒置原则。表面上看它实现了那么多接口其实他通过抽象函数involke的方式把具体的实现传递给了子类,这样子类可以根据业务有更多更具体的实现。 这里需要注意的是最后我们使用了强制类型转换是因为有时候我们是父类转换成子类。 我们在acquire的时候第一个参数是sMessageCallbacksPool,这个成员变量的定义以及初始化是在PooledLambdaImpl中来实现的,这里也是跟我们文章开头关联的地方需要用到Pool了,定义如下: static final Pool sMessageCallbacksPool = new Pool(Message.sPoolSync); static class Pool extends Pools.SynchronizedPool<PooledLambdaImpl> { public Pool(Object lock) { super(MAX_POOL_SIZE, lock); } } 可以看到这里的Pool继承自SynchronizedPool,所以这里也是对对象的池管理。并且初始化了大小。 acquire(pool); 的实现如下: static PooledLambdaImpl acquire(Pool pool) { PooledLambdaImpl r = pool.acquire(); if (r == null) r = new PooledLambdaImpl(); r.mFlags &= ~FLAG_RECYCLED; r.setFlags(FLAG_ACQUIRED_FROM_MESSAGE_CALLBACKS_POOL, pool == sMessageCallbacksPool ? 1 : 0); return r; } 可以看到我们在这里new了一个PooledLambdaImpl实例,并且设置了标志位。通过setIfBounds来管理mArgs数组 private static void setIfInBounds(Object[] array, int i, Object a) { if (i < ArrayUtils.size(array)) array[i] = a; } Object[] mArgs = null; 来管理调用者args参数。从0-8已经涵盖了最长参数的函数。 本次我们acquire的是一个PooledRunnable类型,同样这个类型被OmniFunction实现,实现方法如下: @Override public abstract OmniFunction<A, B, C, D, E, F, G, H, I, R> recycleOnUse(); 哦,这里直接是一个抽象函数那么就要看看我们子类PooledLambdaImpl的实现了。 如下: @Override public OmniFunction<Object, Object, Object, Object, Object, Object, Object, Object, Object, R> recycleOnUse() { if (DEBUG) Log.i(LOG_TAG, this + ".recycleOnUse()"); mFlags |= FLAG_RECYCLE_ON_USE; return this; } |
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 9:18:57- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |