react native内存优化

react native在加载大量图片时小伙伴们会发现,内存一路飙升150M-200M那都不是问题,今天就来优化一下内存,降至40M左右。

1:实现一个module 

import android.app.ActivityManager;
import android.content.Context;
import android.os.Build;
import android.support.annotation.Nullable;
import com.facebook.cache.common.CacheKey;
import com.facebook.cache.disk.DiskCacheConfig;
import com.facebook.common.internal.AndroidPredicates;
import com.facebook.common.internal.Supplier;
import com.facebook.common.soloader.SoLoaderShim;
import com.facebook.common.util.ByteConstants;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.imagepipeline.backends.okhttp3.OkHttpImagePipelineConfigFactory;
import com.facebook.imagepipeline.cache.MemoryCacheParams;
import com.facebook.imagepipeline.core.ImagePipelineConfig;
import com.facebook.imagepipeline.core.ImagePipelineFactory;
import com.facebook.imagepipeline.listener.RequestListener;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.modules.common.ModuleDataCleaner;
import com.facebook.react.modules.fresco.SystraceRequestListener;
import com.facebook.react.modules.network.OkHttpClientProvider;
import com.facebook.soloader.SoLoader;
import java.util.HashSet;
import okhttp3.OkHttpClient;

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.True());
        imagePipelineFactory.getEncodedMemoryCache().removeAll(AndroidPredicates.True());
    }

    private static ImagePipelineConfig getDefaultConfig(
            Context context,
            @Nullable RequestListener listener,
            @Nullable DiskCacheConfig diskCacheConfig) {
        HashSet 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() {
            @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);
        }
    }
}

因为react native在android中使用fresco来加载图片,所以我们自定义自己的fresco来覆盖掉默认的。

2:继承MainReactPackage 实现getNativeMoudules方法 代码如下:

/**
 * Created by xq on 16/11/11.
 */
public class RNMainReactPackage extends MainReactPackage {

    @Override
    public List getNativeModules(ReactApplicationContext context) {
        return Arrays.asList(
                new ModuleSpec(AppStateModule.class, new Provider() {
                    @Override
                    public NativeModule get() {
                        return new AppStateModule(context);
                    }
                }),
                new ModuleSpec(AsyncStorageModule.class, new Provider() {
                    @Override
                    public NativeModule get() {
                        return new AsyncStorageModule(context);
                    }
                }),
                new ModuleSpec(CameraRollManager.class, new Provider() {
                    @Override
                    public NativeModule get() {
                        return new CameraRollManager(context);
                    }
                }),
                new ModuleSpec(ClipboardModule.class, new Provider() {
                    @Override
                    public NativeModule get() {
                        return new ClipboardModule(context);
                    }
                }),
                new ModuleSpec(DatePickerDialogModule.class, new Provider() {
                    @Override
                    public NativeModule get() {
                        return new DatePickerDialogModule(context);
                    }
                }),
                new ModuleSpec(DialogModule.class, new Provider() {
                    @Override
                    public NativeModule get() {
                        return new DialogModule(context);
                    }
                }),
                new ModuleSpec(MyFrescoModule.class, new Provider() {
                    @Override
                    public NativeModule get() {
                        return new MyFrescoModule(context);
                    }
                }),
                new ModuleSpec(I18nManagerModule.class, new Provider() {
                    @Override
                    public NativeModule get() {
                        return new I18nManagerModule(context);
                    }
                }),
                new ModuleSpec(ImageEditingManager.class, new Provider() {
                    @Override
                    public NativeModule get() {
                        return new ImageEditingManager(context);
                    }
                }),
                new ModuleSpec(ImageLoaderModule.class, new Provider() {
                    @Override
                    public NativeModule get() {
                        return new ImageLoaderModule(context);
                    }
                }),
                new ModuleSpec(ImageStoreManager.class, new Provider() {
                    @Override
                    public NativeModule get() {
                        return new ImageStoreManager(context);
                    }
                }),
                new ModuleSpec(IntentModule.class, new Provider() {
                    @Override
                    public NativeModule get() {
                        return new IntentModule(context);
                    }
                }),
                new ModuleSpec(LocationModule.class, new Provider() {
                    @Override
                    public NativeModule get() {
                        return new LocationModule(context);
                    }
                }),
                new ModuleSpec(NativeAnimatedModule.class, new Provider() {
                    @Override
                    public NativeModule get() {
                        return new NativeAnimatedModule(context);
                    }
                }),
                new ModuleSpec(NetworkingModule.class, new Provider() {
                    @Override
                    public NativeModule get() {
                        return new NetworkingModule(context);
                    }
                }),
                new ModuleSpec(NetInfoModule.class, new Provider() {
                    @Override
                    public NativeModule get() {
                        return new NetInfoModule(context);
                    }
                }),
                new ModuleSpec(PermissionsModule.class, new Provider() {
                    @Override
                    public NativeModule get() {
                        return new PermissionsModule(context);
                    }
                }),
                new ModuleSpec(ShareModule.class, new Provider() {
                    @Override
                    public NativeModule get() {
                        return new ShareModule(context);
                    }
                }),
                new ModuleSpec(StatusBarModule.class, new Provider() {
                    @Override
                    public NativeModule get() {
                        return new StatusBarModule(context);
                    }
                }),
                new ModuleSpec(TimePickerDialogModule.class, new Provider() {
                    @Override
                    public NativeModule get() {
                        return new TimePickerDialogModule(context);
                    }
                }),
                new ModuleSpec(ToastModule.class, new Provider() {
                    @Override
                    public NativeModule get() {
                        return new ToastModule(context);
                    }
                }),
                new ModuleSpec(VibrationModule.class, new Provider() {
                    @Override
                    public NativeModule get() {
                        return new VibrationModule(context);
                    }
                }),
                new ModuleSpec(WebSocketModule.class, new Provider() {
                    @Override
                    public NativeModule get() {
                        return new WebSocketModule(context);
                    }
                }));
    }
}

3:在mainapplication的getpackages方法里面替换MainReactPackage

@Override
protected List getPackages() {
  return Arrays.asList(
          new RNMainReactPackage(),
  );
}

4:运行ok. 亲测效果显著。

截图:





你可能感兴趣的:(react-native)