react-native在android中使用fresco来加载图片。说到fresco很多人都会为之欢呼,总比各种轮子内存调优的好。不过在react-native中在它的使用fresco还是稍显随意,如果一个页面是典型的图列表,运行一段时间用dumpsys meminfo命令观察您的程序内存会出现令您惊讶的内存暴增。
为了使得图片内存好看点,我们来修改以下react-native的FrescoModule模块。
public class MyFrescoModule extends ReactContextBaseJavaModule implements
ModuleDataCleaner.Cleanable {
private @Nullable
ImagePipelineConfig mConfig;
public MyFrescoModule(ReactApplicationContext reactContext) {
this(reactContext, getDefaultConfig(reactContext, null, null));
}
public MyFrescoModule(ReactApplicationContext reactContext, RequestListener listener) {
this(reactContext, getDefaultConfig(reactContext, listener, null));
}
public MyFrescoModule(
ReactApplicationContext reactContext,
RequestListener listener,
DiskCacheConfig diskCacheConfig) {
this(reactContext, getDefaultConfig(reactContext, listener, diskCacheConfig));
}
public MyFrescoModule(ReactApplicationContext reactContext, ImagePipelineConfig config) {
super(reactContext);
mConfig = config;
}
@Override
public void initialize() {
super.initialize();
// Make sure the SoLoaderShim is configured to use our loader for native libraries.
// This code can be removed if using Fresco from Maven rather than from source
SoLoaderShim.setHandler(new MyFrescoModule.FrescoHandler());
Context context = getReactApplicationContext().getApplicationContext();
Fresco.initialize(context, mConfig);
mConfig = null;
}
@Override
public String getName() {
return "FrescoModule";
}
@Override
public void clearSensitiveData() {
// Clear image cache.
ImagePipelineFactory imagePipelineFactory = Fresco.getImagePipelineFactory();
imagePipelineFactory.getBitmapMemoryCache().removeAll(AndroidPredicates.<CacheKey>True());
imagePipelineFactory.getEncodedMemoryCache().removeAll(AndroidPredicates.<CacheKey>True());
}
private static ImagePipelineConfig getDefaultConfig(
Context context,
@Nullable RequestListener listener,
@Nullable DiskCacheConfig diskCacheConfig) {
HashSet<RequestListener> requestListeners = new HashSet<>();
requestListeners.add(new SystraceRequestListener());
if (listener != null) {
requestListeners.add(listener);
}
OkHttpClient okHttpClient = OkHttpClientProvider.getOkHttpClient();
ImagePipelineConfig.Builder builder =
OkHttpImagePipelineConfigFactory.newBuilder(context.getApplicationContext(), okHttpClient);
builder
.setDownsampleEnabled(false)
.setRequestListeners(requestListeners);
if (diskCacheConfig != null) {
builder.setMainDiskCacheConfig(diskCacheConfig);
}
final int maxCacheSize= getMaxCacheSize(context);
builder.setBitmapMemoryCacheParamsSupplier(new Supplier<MemoryCacheParams>() {
@Override
public MemoryCacheParams get() {
return new MemoryCacheParams(maxCacheSize,100,0,Integer.MAX_VALUE, Integer.MAX_VALUE);
}
});
return builder.build();
}
private static int getMaxCacheSize(Context context) {
final ActivityManager activityManager=(ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
final int maxMemory = Math.min(activityManager.getMemoryClass() * ByteConstants.MB, Integer.MAX_VALUE);
if (maxMemory < 32 * ByteConstants.MB) {
return 4 * ByteConstants.MB;
} else if (maxMemory < 64 * ByteConstants.MB) {
return 6 * ByteConstants.MB;
} else {
// We don't want to use more ashmem on Gingerbread for now, since it doesn't respond well to
// native memory pressure (doesn't throw exceptions, crashes app, crashes phone)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
return 8 * ByteConstants.MB;
} else {
return maxMemory / 4;
}
}
}
private static class FrescoHandler implements SoLoaderShim.Handler {
@Override
public void loadLibrary(String libraryName) {
SoLoader.loadLibrary(libraryName);
}
}
}
这里我们重新实现了MyFrescoModule,之所以不继承FrescoModule是因为FrescoModule里的getDefaultConfig函数是static的。
下一步继承MainReactPackage 替换掉MainReactPackage ,override createNativeModules方法将FrescoModule替换成MyFrescoModule。
最后run起来再看看您的应用内存是怎样的。祝您好运!