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,listener,null)); } public MyFrescoModule( ReactApplicationContext reactContext,RequestListener listener,DiskCacheConfig diskCacheConfig) { this(reactContext,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,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 ,overridecreateNativeModules方法将FrescoModule替换成MyFrescoModule。
最后run起来再看看您的应用内存是怎样的。祝您好运!