前两篇是类内部实现,LruPoolStrategy的实现不同于前面两篇,它是继承实现的,先看看LruPoolStrategy的源码
LruPoolStrategy包路径:com.bumptech.glide.load.engine.bitmap_recycle.LruPoolStrategy
interface LruPoolStrategy {
void put(Bitmap bitmap);
@Nullable
Bitmap get(int width, int height, Bitmap.Config config);
@Nullable
Bitmap removeLast();
String logBitmap(Bitmap bitmap);
String logBitmap(int width, int height, Bitmap.Config config);
int getSize(Bitmap bitmap);
}
这个接口没有注释,挺少见的。查阅了公开文档也没有找到这个接口的说明, 看接口定义的方法也好理解,这个没有使用public来修饰,也就不对外开发了。接着看看实现类有哪些?
实现类列表- 单元测试应用
- MockStrategy
- AttributeStrategy
- SizeConfigStrategy
- SizeStrategy
包路径:com.bumptech.glide.load.engine.bitmap_recycle.LruBitmapPoolTest
private MockStrategy strategy;
。。。
@Test
public void testBitmapLargerThanPoolIsNotAdded() {
strategy =
new MockStrategy() {
@Override
public int getSize(Bitmap bitmap) {
return 4;
}
};
pool = new LruBitmapPool(3, strategy, ALLOWED_CONFIGS);
pool.put(createMutableBitmap());
assertEquals(0, strategy.numRemoves);
assertEquals(0, strategy.numPuts);
}
MockStrategy
包路径:com.bumptech.glide.load.engine.bitmap_recycle.LruBitmapPoolTest.MockStrategy
private static class MockStrategy implements LruPoolStrategy {
private final ArrayDeque bitmaps = new ArrayDeque();
private int numRemoves;
private int numPuts;
@Override
public void put(Bitmap bitmap) {
numPuts++;
bitmaps.add(bitmap);
}
@Override
public Bitmap get(int width, int height, Bitmap.Config config) {
return bitmaps.isEmpty() ? null : bitmaps.removeLast();
}
@Override
public Bitmap removeLast() {
numRemoves++;
return bitmaps.removeLast();
}
@Override
public String logBitmap(Bitmap bitmap) {
return null;
}
@Override
public String logBitmap(int width, int height, Bitmap.Config config) {
return null;
}
@Override
public int getSize(Bitmap bitmap) {
return 1;
}
}
这个是用来进行单元测试的桩实现。具体实现比较简单一些,这个放在前面会好理解一些。
AttributeStrategy包路径:com.bumptech.glide.load.engine.bitmap_recycle.AttributeStrategy
一种重用位图的策略,需要任何返回的位图的尺寸来精确匹配这些请求
/**
* A strategy for reusing bitmaps that requires any returned bitmap's dimensions to exactly match
* those request.
*/
一种重用位图的策略,需要任何返回的位图的尺寸来精确匹配这些请求
class AttributeStrategy implements LruPoolStrategy {
private final KeyPool keyPool = new KeyPool();
private final GroupedLinkedMap groupedMap = new GroupedLinkedMap();
@Override
public void put(Bitmap bitmap) {
final Key key = keyPool.get(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
groupedMap.put(key, bitmap);
}
@Override
public Bitmap get(int width, int height, Bitmap.Config config) {
final Key key = keyPool.get(width, height, config);
return groupedMap.get(key);
}
@Override
public Bitmap removeLast() {
return groupedMap.removeLast();
}
@Override
public String logBitmap(Bitmap bitmap) {
return getBitmapString(bitmap);
}
@Override
public String logBitmap(int width, int height, Bitmap.Config config) {
return getBitmapString(width, height, config);
}
@Override
public int getSize(Bitmap bitmap) {
return Util.getBitmapByteSize(bitmap);
}
@Override
public String toString() {
return "AttributeStrategy:\n " + groupedMap;
}
private static String getBitmapString(Bitmap bitmap) {
return getBitmapString(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
}
@SuppressWarnings("WeakerAccess")
@Synthetic
static String getBitmapString(int width, int height, Bitmap.Config config) {
return "[" + width + "x" + height + "], " + config;
}
@VisibleForTesting
static class KeyPool extends BaseKeyPool {
Key get(int width, int height, Bitmap.Config config) {
Key result = get();
result.init(width, height, config);
return result;
}
@Override
protected Key create() {
return new Key(this);
}
}
@VisibleForTesting
static class Key implements Poolable {
private final KeyPool pool;
private int width;
private int height;
// Config can be null :(
private Bitmap.Config config;
public Key(KeyPool pool) {
this.pool = pool;
}
public void init(int width, int height, Bitmap.Config config) {
this.width = width;
this.height = height;
this.config = config;
}
@Override
public boolean equals(Object o) {
if (o instanceof Key) {
Key other = (Key) o;
return width == other.width && height == other.height && config == other.config;
}
return false;
}
@Override
public int hashCode() {
int result = width;
result = 31 * result + height;
result = 31 * result + (config != null ? config.hashCode() : 0);
return result;
}
@Override
public String toString() {
return getBitmapString(width, height, config);
}
@Override
public void offer() {
pool.offer(this);
}
}
单独看这个一个实现没发现什么特别的,接着看看下面的实现类
SizeConfigStrategy包路径:com.bumptech.glide.load.engine.bitmap_recycle.SizeConfigStrategy
使用Bitmap. getallocationbytecount()和Bitmap键位图。从Bitmap.getConfig()返回的配置。 同时使用配置和字节大小允许我们安全地复用各种各样的位图,这提高了池的命中率,从而提高了应用程序的性能。这个类只允许复用每像素匹配字节数的位图,工作在#301左右。
/**
* Keys {@link android.graphics.Bitmap Bitmaps} using both {@link
* android.graphics.Bitmap#getAllocationByteCount()} and the {@link android.graphics.Bitmap.Config}
* returned from {@link android.graphics.Bitmap#getConfig()}.
*
* Using both the config and the byte size allows us to safely re-use a greater variety of {@link
* android.graphics.Bitmap Bitmaps}, which increases the hit rate of the pool and therefore the
* performance of applications. This class works around #301 by only allowing re-use of {@link
* android.graphics.Bitmap Bitmaps} with a matching number of bytes per pixel.
*/
使用Bitmap. getallocationbytecount()和Bitmap键位图。从Bitmap.getConfig()返回的配置。
同时使用配置和字节大小允许我们安全地复用各种各样的位图,这提高了池的命中率,从而提高了应用程序的性能。这个类只允许复用每像素匹配字节数的位图,工作在#301左右。
@RequiresApi(Build.VERSION_CODES.KITKAT)
public class SizeConfigStrategy implements LruPoolStrategy {
private static final int MAX_SIZE_MULTIPLE = 8;
private static final Bitmap.Config[] ARGB_8888_IN_CONFIGS;
static {
Bitmap.Config[] result =
new Bitmap.Config[] {
Bitmap.Config.ARGB_8888,
// The value returned by Bitmaps with the hidden Bitmap config.
null,
};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
result = Arrays.copyOf(result, result.length + 1);
result[result.length - 1] = Config.RGBA_F16;
}
ARGB_8888_IN_CONFIGS = result;
}
private static final Bitmap.Config[] RGBA_F16_IN_CONFIGS = ARGB_8888_IN_CONFIGS;
// We probably could allow ARGB_4444 and RGB_565 to decode into each other, but ARGB_4444 is
// deprecated and we'd rather be safe.
private static final Bitmap.Config[] RGB_565_IN_CONFIGS =
new Bitmap.Config[] {Bitmap.Config.RGB_565};
private static final Bitmap.Config[] ARGB_4444_IN_CONFIGS =
new Bitmap.Config[] {Bitmap.Config.ARGB_4444};
private static final Bitmap.Config[] ALPHA_8_IN_CONFIGS =
new Bitmap.Config[] {Bitmap.Config.ALPHA_8};
private final KeyPool keyPool = new KeyPool();
private final GroupedLinkedMap groupedMap = new GroupedLinkedMap();
private final Map sortedSizes = new HashMap();
@Override
public void put(Bitmap bitmap) {
int size = Util.getBitmapByteSize(bitmap);
Key key = keyPool.get(size, bitmap.getConfig());
groupedMap.put(key, bitmap);
NavigableMap sizes = getSizesForConfig(bitmap.getConfig());
Integer current = sizes.get(key.size);
sizes.put(key.size, current == null ? 1 : current + 1);
}
@Override
@Nullable
public Bitmap get(int width, int height, Bitmap.Config config) {
int size = Util.getBitmapByteSize(width, height, config);
Key bestKey = findBestKey(size, config);
Bitmap result = groupedMap.get(bestKey);
if (result != null) {
// Decrement must be called before reconfigure.
decrementBitmapOfSize(bestKey.size, result);
result.reconfigure(width, height, config);
}
return result;
}
private Key findBestKey(int size, Bitmap.Config config) {
Key result = keyPool.get(size, config);
for (Bitmap.Config possibleConfig : getInConfigs(config)) {
NavigableMap sizesForPossibleConfig = getSizesForConfig(possibleConfig);
Integer possibleSize = sizesForPossibleConfig.ceilingKey(size);
if (possibleSize != null && possibleSize = Build.VERSION_CODES.O) {
if (Bitmap.Config.RGBA_F16.equals(requested)) { // NOPMD - Avoid short circuiting sdk checks.
return RGBA_F16_IN_CONFIGS;
}
}
switch (requested) {
case ARGB_8888:
return ARGB_8888_IN_CONFIGS;
case RGB_565:
return RGB_565_IN_CONFIGS;
case ARGB_4444:
return ARGB_4444_IN_CONFIGS;
case ALPHA_8:
return ALPHA_8_IN_CONFIGS;
default:
return new Bitmap.Config[] {requested};
}
}
}
AttributeStrategy#put(Bitmap bitmap) VS SizeConfigStrategy#put(Bitmap bitmap)
AttributeStrategy
public void put(Bitmap bitmap) {
final Key key = keyPool.get(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
groupedMap.put(key, bitmap);
}
SizeConfigStrategy
@Override
public void put(Bitmap bitmap) {
int size = Util.getBitmapByteSize(bitmap);
Key key = keyPool.get(size, bitmap.getConfig());
groupedMap.put(key, bitmap);
NavigableMap sizes = getSizesForConfig(bitmap.getConfig());
Integer current = sizes.get(key.size);
sizes.put(key.size, current == null ? 1 : current + 1);
}
很显然算法策略输入参数不一样, AttributeStrategy的key由bitmap的属性Width、Height、Config SizeConfigStrategy的key由bitmap的size、config组成 相对比较一下SizeConfigStrategy安全性比较高一些。但计算性能方面会消耗大一些,其他方法实现与各自的put(Bitmap bitmap)保持一致,这里不具体说明了。 再看一个
SizeStrategy包路径:com.bumptech.glide.load.engine.bitmap_recycle.SizeStrategy 这个策略并没有对外公开,但看其具体实现和SizeConfigStrategy相似度较高。和其他两个比较着看会好理解一些
基于Bitmap#reconfigure(int, int,Bitmap.Config)的位图复用策略
/**
* A strategy for reusing bitmaps that relies on {@link Bitmap#reconfigure(int, int,
* Bitmap.Config)}.
*
* Requires {@link Build.VERSION_CODES#KITKAT KitKat} or higher.
*/
@RequiresApi(Build.VERSION_CODES.KITKAT)
final class SizeStrategy implements LruPoolStrategy {
private static final int MAX_SIZE_MULTIPLE = 8;
private final KeyPool keyPool = new KeyPool();
private final GroupedLinkedMap groupedMap = new GroupedLinkedMap();
private final NavigableMap sortedSizes = new PrettyPrintTreeMap();
@Override
public void put(Bitmap bitmap) {
int size = Util.getBitmapByteSize(bitmap);
final Key key = keyPool.get(size);
groupedMap.put(key, bitmap);
Integer current = sortedSizes.get(key.size);
sortedSizes.put(key.size, current == null ? 1 : current + 1);
}
@Override
@Nullable
public Bitmap get(int width, int height, Bitmap.Config config) {
final int size = Util.getBitmapByteSize(width, height, config);
Key key = keyPool.get(size);
Integer possibleSize = sortedSizes.ceilingKey(size);
if (possibleSize != null && possibleSize != size && possibleSize
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?