From c0de1a7011846e780d9ddfb9d4427b8b17830c0a Mon Sep 17 00:00:00 2001 From: Alexander Oprisnik Date: Wed, 31 Aug 2016 14:49:56 -0700 Subject: [PATCH] Only initialize FrescoModule once Summary: Fresco should only be initialized once. Re-initializing causes a few problems (https://github.com/facebook/react-native/issues/8677) and we don't need to do it. If a Fresco configuration needs to change, you can just restart the application or add delegates for parts that can change and manually update them instead. Reviewed By: astreet Differential Revision: D3790908 fbshipit-source-id: 9df4c3be15ca49433120abd7ba1a4f5ae2a3f1c1 --- .../com/facebook/react/modules/fresco/BUCK | 2 + .../react/modules/fresco/FrescoModule.java | 97 +++++++++++-------- 2 files changed, 57 insertions(+), 42 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/BUCK index 0f462adbc3a35b..367f8cf4898ccc 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/BUCK @@ -5,6 +5,7 @@ android_library( srcs = glob(['**/*.java']), deps = [ react_native_dep('java/com/facebook/systrace:systrace'), + react_native_dep('libraries/fbcore/src/main/java/com/facebook/common/logging:logging'), react_native_dep('libraries/fresco/fresco-react-native:fbcore'), react_native_dep('libraries/fresco/fresco-react-native:fresco-drawee'), react_native_dep('libraries/fresco/fresco-react-native:fresco-react-native'), @@ -16,6 +17,7 @@ android_library( react_native_dep('third-party/java/jsr-305:jsr-305'), react_native_dep('third-party/java/okhttp:okhttp3'), react_native_target('java/com/facebook/react/bridge:bridge'), + react_native_target('java/com/facebook/react/common:common'), react_native_target('java/com/facebook/react/modules/common:common'), react_native_target('java/com/facebook/react/modules/network:network'), ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/FrescoModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/FrescoModule.java index 95b54fdd4d7a47..6ce077625583ac 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/FrescoModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/FrescoModule.java @@ -14,20 +14,19 @@ import android.content.Context; import android.support.annotation.Nullable; -import com.facebook.cache.disk.DiskCacheConfig; import com.facebook.common.soloader.SoLoaderShim; +import com.facebook.common.logging.FLog; import com.facebook.drawee.backends.pipeline.Fresco; import com.facebook.imagepipeline.backends.okhttp3.OkHttpImagePipelineConfigFactory; import com.facebook.imagepipeline.core.ImagePipelineConfig; import com.facebook.imagepipeline.listener.RequestListener; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.common.ReactConstants; import com.facebook.react.modules.common.ModuleDataCleaner; import com.facebook.react.modules.network.OkHttpClientProvider; import com.facebook.soloader.SoLoader; -import okhttp3.OkHttpClient; - /** * Module to initialize the Fresco library. * @@ -38,22 +37,29 @@ public class FrescoModule extends ReactContextBaseJavaModule implements private @Nullable ImagePipelineConfig mConfig; - public FrescoModule(ReactApplicationContext reactContext) { - this(reactContext, getDefaultConfig(reactContext, null, null)); - } - - public FrescoModule(ReactApplicationContext reactContext, RequestListener listener) { - this(reactContext, getDefaultConfig(reactContext, listener, null)); - } + private static boolean sHasBeenInitialized = false; - public FrescoModule( - ReactApplicationContext reactContext, - RequestListener listener, - DiskCacheConfig diskCacheConfig) { - this(reactContext, getDefaultConfig(reactContext, listener, diskCacheConfig)); + /** + * Create a new Fresco module with a default configuration (or the previously given + * configuration via {@link #FrescoModule(ReactApplicationContext, ImagePipelineConfig)}. + * + * @param reactContext the context to use + */ + public FrescoModule(ReactApplicationContext reactContext) { + this(reactContext, null); } - public FrescoModule(ReactApplicationContext reactContext, ImagePipelineConfig config) { + /** + * Create a new Fresco module with a given ImagePipelineConfig. + * This should only be called when the module has not been initialized yet. + * You can use {@link #hasBeenInitialized()} to check this and call + * {@link #FrescoModule(ReactApplicationContext)} if it is already initialized. + * Otherwise, the given Fresco configuration will be ignored. + * + * @param reactContext the context to use + * @param config the Fresco configuration, which will only be used for the first initialization + */ + public FrescoModule(ReactApplicationContext reactContext, @Nullable ImagePipelineConfig config) { super(reactContext); mConfig = config; } @@ -61,12 +67,22 @@ public FrescoModule(ReactApplicationContext reactContext, ImagePipelineConfig co @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 FrescoHandler()); - - Context context = getReactApplicationContext().getApplicationContext(); - Fresco.initialize(context, mConfig); + if (!hasBeenInitialized()) { + // 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 FrescoHandler()); + if (mConfig == null) { + mConfig = getDefaultConfig(getReactApplicationContext()); + } + Context context = getReactApplicationContext().getApplicationContext(); + Fresco.initialize(context, mConfig); + sHasBeenInitialized = true; + } else if (mConfig != null) { + FLog.w( + ReactConstants.TAG, + "Fresco has already been initialized with a different config. " + + "The new Fresco configuration will be ignored!"); + } mConfig = null; } @@ -81,29 +97,26 @@ public void clearSensitiveData() { Fresco.getImagePipeline().clearCaches(); } - private static ImagePipelineConfig getDefaultConfig( - Context context, - @Nullable RequestListener listener, - @Nullable DiskCacheConfig diskCacheConfig) { + /** + * Check whether the FrescoModule has already been initialized. If this is the case, + * Calls to {@link #FrescoModule(ReactApplicationContext, ImagePipelineConfig)} will + * ignore the given configuration. + * + * @return true if this module has already been initialized + */ + public static boolean hasBeenInitialized() { + return sHasBeenInitialized; + } + + private static ImagePipelineConfig getDefaultConfig(Context context) { 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); - } - return builder.build(); + return OkHttpImagePipelineConfigFactory + .newBuilder(context.getApplicationContext(), OkHttpClientProvider.getOkHttpClient()) + .setDownsampleEnabled(false) + .setRequestListeners(requestListeners) + .build(); } private static class FrescoHandler implements SoLoaderShim.Handler {