feat: add Resource Cache for loading the same resource
This commit is contained in:
		| @@ -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); | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user