react-native内存优化--图片内存

原创
2016/10/17 14:47
阅读数 9K

    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起来再看看您的应用内存是怎样的。祝您好运!

展开阅读全文
打赏
0
5 收藏
分享
加载中
更多评论
打赏
0 评论
5 收藏
0
分享
返回顶部
顶部