feat: add Resource Cache for loading the same resource
This commit is contained in:
parent
5b80e4e0e1
commit
3bedd8034c
@ -18,6 +18,7 @@ package pub.doric.resource;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
@ -32,19 +33,19 @@ public class DoricResourceManager {
|
|||||||
private final Map<String, DoricResourceLoader> mResourceLoaders = new HashMap<>();
|
private final Map<String, DoricResourceLoader> mResourceLoaders = new HashMap<>();
|
||||||
private final Map<String, DoricResource> cachedResources = new WeakHashMap<>();
|
private final Map<String, DoricResource> cachedResources = new WeakHashMap<>();
|
||||||
|
|
||||||
public void registerLoader(DoricResourceLoader loader) {
|
public synchronized void registerLoader(DoricResourceLoader loader) {
|
||||||
mResourceLoaders.put(loader.resourceType(), loader);
|
mResourceLoaders.put(loader.resourceType(), loader);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unRegisterLoader(DoricResourceLoader loader) {
|
public synchronized void unRegisterLoader(DoricResourceLoader loader) {
|
||||||
mResourceLoaders.remove(loader.resourceType());
|
mResourceLoaders.remove(loader.resourceType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public DoricResource load(@NonNull DoricContext doricContext,
|
public synchronized DoricResource load(@NonNull DoricContext doricContext,
|
||||||
@NonNull String resId,
|
@NonNull String resId,
|
||||||
@NonNull String type,
|
@NonNull String type,
|
||||||
@NonNull String identifier) {
|
@NonNull String identifier) {
|
||||||
DoricResource resource = cachedResources.get(resId);
|
DoricResource resource = cachedResources.get(resId);
|
||||||
if (resource == null) {
|
if (resource == null) {
|
||||||
DoricResourceLoader loader = mResourceLoaders.get(type);
|
DoricResourceLoader loader = mResourceLoaders.get(type);
|
||||||
|
@ -25,7 +25,8 @@
|
|||||||
|
|
||||||
- (void)unRegisterLoader:(id <DoricResourceLoader>)loader;
|
- (void)unRegisterLoader:(id <DoricResourceLoader>)loader;
|
||||||
|
|
||||||
- (__kindof DoricResource *)load:(NSString *)identifier
|
- (__kindof DoricResource *)load:(NSString *)resId
|
||||||
|
withIdentifier:(NSString *)identifier
|
||||||
withResourceType:(NSString *)resourceType
|
withResourceType:(NSString *)resourceType
|
||||||
withContext:(DoricContext *)context;
|
withContext:(DoricContext *)context;
|
||||||
@end
|
@end
|
||||||
|
@ -21,29 +21,48 @@
|
|||||||
|
|
||||||
@interface DoricResourceManager ()
|
@interface DoricResourceManager ()
|
||||||
@property(nonatomic, strong) NSMutableDictionary <NSString *, id <DoricResourceLoader>> *loaders;
|
@property(nonatomic, strong) NSMutableDictionary <NSString *, id <DoricResourceLoader>> *loaders;
|
||||||
|
@property(nonatomic, strong) NSMapTable <NSString *, __kindof DoricResource *> *cachedResources;
|
||||||
|
@property(nonatomic, strong) dispatch_queue_t mapQueue;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation DoricResourceManager
|
@implementation DoricResourceManager
|
||||||
- (instancetype)init {
|
- (instancetype)init {
|
||||||
if (self = [super init]) {
|
if (self = [super init]) {
|
||||||
_loaders = [NSMutableDictionary new];
|
_loaders = [NSMutableDictionary new];
|
||||||
|
_mapQueue = dispatch_queue_create("doric.resource", DISPATCH_QUEUE_SERIAL);
|
||||||
|
_cachedResources = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsCopyIn
|
||||||
|
valueOptions:NSPointerFunctionsWeakMemory
|
||||||
|
capacity:0];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)registerLoader:(id <DoricResourceLoader>)loader {
|
- (void)registerLoader:(id <DoricResourceLoader>)loader {
|
||||||
self.loaders[loader.resourceType] = loader;
|
dispatch_sync(self.mapQueue, ^{
|
||||||
|
self.loaders[loader.resourceType] = loader;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)unRegisterLoader:(id <DoricResourceLoader>)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
|
withResourceType:(NSString *)resourceType
|
||||||
withContext:(DoricContext *)context {
|
withContext:(DoricContext *)context {
|
||||||
id <DoricResourceLoader> loader = self.loaders[resourceType];
|
__block __kindof DoricResource *resource;
|
||||||
return [loader load:identifier withContext:context];
|
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
|
@end
|
||||||
|
@ -238,8 +238,12 @@ - (void)blendView:(UIImageView *)view forPropName:(NSString *)name propValue:(id
|
|||||||
if ([@"image" isEqualToString:name]) {
|
if ([@"image" isEqualToString:name]) {
|
||||||
NSString *type = prop[@"type"];
|
NSString *type = prop[@"type"];
|
||||||
NSString *identifier = prop[@"identifier"];
|
NSString *identifier = prop[@"identifier"];
|
||||||
|
NSString *resId = prop[@"resId"];
|
||||||
DoricAsyncResult <NSData *> *asyncResult = [[self.doricContext.driver.registry.loaderManager
|
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) {
|
[asyncResult setResultCallback:^(NSData *imageData) {
|
||||||
[self.doricContext dispatchToMainQueue:^{
|
[self.doricContext dispatchToMainQueue:^{
|
||||||
#if DORIC_USE_YYWEBIMAGE
|
#if DORIC_USE_YYWEBIMAGE
|
||||||
|
Reference in New Issue
Block a user