From d9ae27ba89c0beda0c76d3a227c2a453948db1a2 Mon Sep 17 00:00:00 2001 From: Felix Oghina Date: Fri, 10 Mar 2017 06:36:16 -0800 Subject: [PATCH] Clear Fresco memory cache in onHostDestroy Summary: `onHostDestroy` is when the app is backgrounded and all Activities are destroyed. At this point it's safe to clear Fresco's memory cache. Reviewed By: AaaChiuuu Differential Revision: D4674950 fbshipit-source-id: f6db658ad56e3ad843cd2acfa31e2df1c40d3279 --- .../react/modules/fresco/FrescoModule.java | 50 +++++++++++++++++-- .../react/shell/MainReactPackage.java | 2 +- 2 files changed, 47 insertions(+), 5 deletions(-) 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 0d1a2183f..e1e227e59 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 @@ -20,6 +20,7 @@ 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.LifecycleEventListener; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; @@ -41,20 +42,35 @@ import okhttp3.OkHttpClient; */ @ReactModule(name = "FrescoModule") public class FrescoModule extends ReactContextBaseJavaModule implements - ModuleDataCleaner.Cleanable { + ModuleDataCleaner.Cleanable, LifecycleEventListener { + private final boolean mClearOnDestroy; private @Nullable ImagePipelineConfig mConfig; private static boolean sHasBeenInitialized = false; /** * Create a new Fresco module with a default configuration (or the previously given - * configuration via {@link #FrescoModule(ReactApplicationContext, ImagePipelineConfig)}. + * configuration via {@link #FrescoModule(ReactApplicationContext, boolean, ImagePipelineConfig)}. * * @param reactContext the context to use */ public FrescoModule(ReactApplicationContext reactContext) { - this(reactContext, null); + this(reactContext, true, null); + } + + /** + * Create a new Fresco module with a default configuration (or the previously given + * configuration via {@link #FrescoModule(ReactApplicationContext, boolean, ImagePipelineConfig)}. + * + * @param clearOnDestroy whether to clear the memory cache in onHostDestroy: this should be + * {@code true} for pure RN apps and {@code false} for apps that use Fresco outside of RN + * as well + * @param reactContext the context to use + * + */ + public FrescoModule(ReactApplicationContext reactContext, boolean clearOnDestroy) { + this(reactContext, clearOnDestroy, null); } /** @@ -65,16 +81,24 @@ public class FrescoModule extends ReactContextBaseJavaModule implements * Otherwise, the given Fresco configuration will be ignored. * * @param reactContext the context to use + * @param clearOnDestroy whether to clear the memory cache in onHostDestroy: this should be + * {@code true} for pure RN apps and {@code false} for apps that use Fresco outside of RN + * as well * @param config the Fresco configuration, which will only be used for the first initialization */ - public FrescoModule(ReactApplicationContext reactContext, @Nullable ImagePipelineConfig config) { + public FrescoModule( + ReactApplicationContext reactContext, + boolean clearOnDestroy, + @Nullable ImagePipelineConfig config) { super(reactContext); + mClearOnDestroy = clearOnDestroy; mConfig = config; } @Override public void initialize() { super.initialize(); + getReactApplicationContext().addLifecycleEventListener(this); 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 @@ -145,6 +169,24 @@ public class FrescoModule extends ReactContextBaseJavaModule implements .setRequestListeners(requestListeners); } + @Override + public void onHostResume() { + } + + @Override + public void onHostPause() { + } + + @Override + public void onHostDestroy() { + // According to the javadoc for LifecycleEventListener#onHostDestroy, this is only called when + // the 'last' ReactActivity is being destroyed, which effectively means the app is being + // backgrounded. + if (mClearOnDestroy) { + Fresco.getImagePipeline().clearMemoryCaches(); + } + } + private static class FrescoHandler implements SoLoaderShim.Handler { @Override public void loadLibrary(String libraryName) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java b/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java index a47ecb326..7d076813a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java +++ b/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java @@ -148,7 +148,7 @@ public class MainReactPackage extends LazyReactPackage { new ModuleSpec(FrescoModule.class, new Provider() { @Override public NativeModule get() { - return new FrescoModule(context, mConfig != null ? mConfig.getFrescoConfig() : null); + return new FrescoModule(context, true, mConfig != null ? mConfig.getFrescoConfig() : null); } }), new ModuleSpec(I18nManagerModule.class, new Provider() {