feat: add Resource Cache for loading the same resource

This commit is contained in:
pengfei.zhou 2021-11-18 18:15:36 +08:00 committed by osborn
parent 5b80e4e0e1
commit 3bedd8034c
4 changed files with 38 additions and 13 deletions

View File

@ -18,6 +18,7 @@ package pub.doric.resource;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -32,19 +33,19 @@ public class DoricResourceManager {
private final Map<String, DoricResourceLoader> mResourceLoaders = new HashMap<>();
private final Map<String, DoricResource> cachedResources = new WeakHashMap<>();
public void registerLoader(DoricResourceLoader loader) {
public synchronized void registerLoader(DoricResourceLoader loader) {
mResourceLoaders.put(loader.resourceType(), loader);
}
public void unRegisterLoader(DoricResourceLoader loader) {
public synchronized void unRegisterLoader(DoricResourceLoader loader) {
mResourceLoaders.remove(loader.resourceType());
}
@Nullable
public DoricResource load(@NonNull DoricContext doricContext,
@NonNull String resId,
@NonNull String type,
@NonNull String identifier) {
public synchronized DoricResource load(@NonNull DoricContext doricContext,
@NonNull String resId,
@NonNull String type,
@NonNull String identifier) {
DoricResource resource = cachedResources.get(resId);
if (resource == null) {
DoricResourceLoader loader = mResourceLoaders.get(type);

View File

@ -25,7 +25,8 @@
- (void)unRegisterLoader:(id <DoricResourceLoader>)loader;
- (__kindof DoricResource *)load:(NSString *)identifier
- (__kindof DoricResource *)load:(NSString *)resId
withIdentifier:(NSString *)identifier
withResourceType:(NSString *)resourceType
withContext:(DoricContext *)context;
@end

View File

@ -21,29 +21,48 @@
@interface DoricResourceManager ()
@property(nonatomic, strong) NSMutableDictionary <NSString *, id <DoricResourceLoader>> *loaders;
@property(nonatomic, strong) NSMapTable <NSString *, __kindof DoricResource *> *cachedResources;
@property(nonatomic, strong) dispatch_queue_t mapQueue;
@end
@implementation DoricResourceManager
- (instancetype)init {
if (self = [super init]) {
_loaders = [NSMutableDictionary new];
_mapQueue = dispatch_queue_create("doric.resource", DISPATCH_QUEUE_SERIAL);
_cachedResources = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsCopyIn
valueOptions:NSPointerFunctionsWeakMemory
capacity:0];
}
return self;
}
- (void)registerLoader:(id <DoricResourceLoader>)loader {
self.loaders[loader.resourceType] = loader;
dispatch_sync(self.mapQueue, ^{
self.loaders[loader.resourceType] = loader;
});
}
- (void)unRegisterLoader:(id <DoricResourceLoader>)loader {
[self.loaders removeObjectForKey:loader.resourceType];
dispatch_sync(self.mapQueue, ^{
[self.loaders removeObjectForKey:loader.resourceType];
});
}
- (__kindof DoricResource *)load:(NSString *)identifier
- (__kindof DoricResource *)load:(NSString *)resId
withIdentifier:(NSString *)identifier
withResourceType:(NSString *)resourceType
withContext:(DoricContext *)context {
id <DoricResourceLoader> loader = self.loaders[resourceType];
return [loader load:identifier withContext:context];
__block __kindof DoricResource *resource;
dispatch_sync(self.mapQueue, ^() {
resource = [self.cachedResources objectForKey:resId];
if (!resource) {
id <DoricResourceLoader> loader = self.loaders[resourceType];
resource = [loader load:identifier withContext:context];
[self.cachedResources setObject:resource forKey:resId];
}
});
return resource;
}
@end

View File

@ -238,8 +238,12 @@ - (void)blendView:(UIImageView *)view forPropName:(NSString *)name propValue:(id
if ([@"image" isEqualToString:name]) {
NSString *type = prop[@"type"];
NSString *identifier = prop[@"identifier"];
NSString *resId = prop[@"resId"];
DoricAsyncResult <NSData *> *asyncResult = [[self.doricContext.driver.registry.loaderManager
load:identifier withResourceType:type withContext:self.doricContext] fetchRaw];
load:resId
withIdentifier:identifier
withResourceType:type
withContext:self.doricContext] fetchRaw];
[asyncResult setResultCallback:^(NSData *imageData) {
[self.doricContext dispatchToMainQueue:^{
#if DORIC_USE_YYWEBIMAGE