From 3bedd8034c95959e8e8cd5f15307a30b50890f54 Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Thu, 18 Nov 2021 18:15:36 +0800 Subject: [PATCH] feat: add Resource Cache for loading the same resource --- .../doric/resource/DoricResourceManager.java | 13 +++++---- .../Classes/Resource/DoricResourceManager.h | 3 +- .../Classes/Resource/DoricResourceManager.m | 29 +++++++++++++++---- doric-iOS/Pod/Classes/Shader/DoricImageNode.m | 6 +++- 4 files changed, 38 insertions(+), 13 deletions(-) diff --git a/doric-android/doric/src/main/java/pub/doric/resource/DoricResourceManager.java b/doric-android/doric/src/main/java/pub/doric/resource/DoricResourceManager.java index f0c137f5..d600193e 100644 --- a/doric-android/doric/src/main/java/pub/doric/resource/DoricResourceManager.java +++ b/doric-android/doric/src/main/java/pub/doric/resource/DoricResourceManager.java @@ -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 mResourceLoaders = new HashMap<>(); private final Map 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); diff --git a/doric-iOS/Pod/Classes/Resource/DoricResourceManager.h b/doric-iOS/Pod/Classes/Resource/DoricResourceManager.h index 788e9ec7..c1111dc8 100644 --- a/doric-iOS/Pod/Classes/Resource/DoricResourceManager.h +++ b/doric-iOS/Pod/Classes/Resource/DoricResourceManager.h @@ -25,7 +25,8 @@ - (void)unRegisterLoader:(id )loader; -- (__kindof DoricResource *)load:(NSString *)identifier +- (__kindof DoricResource *)load:(NSString *)resId + withIdentifier:(NSString *)identifier withResourceType:(NSString *)resourceType withContext:(DoricContext *)context; @end diff --git a/doric-iOS/Pod/Classes/Resource/DoricResourceManager.m b/doric-iOS/Pod/Classes/Resource/DoricResourceManager.m index 22ae6dac..caca861f 100644 --- a/doric-iOS/Pod/Classes/Resource/DoricResourceManager.m +++ b/doric-iOS/Pod/Classes/Resource/DoricResourceManager.m @@ -21,29 +21,48 @@ @interface DoricResourceManager () @property(nonatomic, strong) NSMutableDictionary > *loaders; +@property(nonatomic, strong) NSMapTable *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 )loader { - self.loaders[loader.resourceType] = loader; + dispatch_sync(self.mapQueue, ^{ + self.loaders[loader.resourceType] = loader; + }); } - (void)unRegisterLoader:(id )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 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 loader = self.loaders[resourceType]; + resource = [loader load:identifier withContext:context]; + [self.cachedResources setObject:resource forKey:resId]; + } + }); + return resource; } @end diff --git a/doric-iOS/Pod/Classes/Shader/DoricImageNode.m b/doric-iOS/Pod/Classes/Shader/DoricImageNode.m index 0d325833..62569807 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricImageNode.m +++ b/doric-iOS/Pod/Classes/Shader/DoricImageNode.m @@ -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 *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