Skip to content

Commit b12f574

Browse files
falhassenglide-copybara-robot
authored andcommitted
Allow limiting the size of LruBitmapPool/MemoryCache when in background
When an app is moved to background, onTrimMemory() will be called, and LruBitmapPool/MemoryCache will be trimmed. However, the app could keep running and will new bitmaps will be retired to MemoryCache and LruBitmapPool. This change limits the sizes of LruBitmapPool/MemoryCache to zero when the app is in background, and restore the sizes to normal when it's moved out of background. We introduce an experimental API `setMemoryCategoryInBackground(MemoryCategory)` for this purpose, as well as a new `MemoryCategory.ZERO` for no pooling/caching. App can use this API to set the MemoryCategory to limit the pool/cache size when the app is in background. PiperOrigin-RevId: 856285259
1 parent 82657e9 commit b12f574

File tree

3 files changed

+130
-0
lines changed

3 files changed

+130
-0
lines changed

library/src/main/java/com/bumptech/glide/Glide.java

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package com.bumptech.glide;
22

33
import android.app.Activity;
4+
import android.app.Application;
45
import android.content.ComponentCallbacks2;
56
import android.content.Context;
67
import android.content.res.Configuration;
78
import android.graphics.Bitmap;
9+
import android.os.Bundle;
810
import android.os.MessageQueue.IdleHandler;
911
import android.util.Log;
1012
import android.view.View;
@@ -33,6 +35,7 @@
3335
import com.bumptech.glide.request.RequestOptions;
3436
import com.bumptech.glide.request.target.ImageViewTargetFactory;
3537
import com.bumptech.glide.request.target.Target;
38+
import com.bumptech.glide.util.GlideSuppliers;
3639
import com.bumptech.glide.util.GlideSuppliers.GlideSupplier;
3740
import com.bumptech.glide.util.Preconditions;
3841
import com.bumptech.glide.util.Util;
@@ -81,6 +84,13 @@ public class Glide implements ComponentCallbacks2 {
8184
@Nullable
8285
private BitmapPreFiller bitmapPreFiller;
8386

87+
private boolean inBackground = false;
88+
private MemoryCategory memoryCategoryInBackground = null;
89+
private MemoryCategory memoryCategoryInForeground = MemoryCategory.NORMAL;
90+
91+
private final GlideSupplier<SetMemoryCategoryOnLifecycleCallbacks> setMemoryCategoryCallbacks =
92+
GlideSuppliers.memorize(SetMemoryCategoryOnLifecycleCallbacks::new);
93+
8494
/**
8595
* Returns a directory with a default name in the private cache directory of the application to
8696
* use to store retrieved media and thumbnails.
@@ -206,6 +216,7 @@ public static void tearDown() {
206216
synchronized (Glide.class) {
207217
if (glide != null) {
208218
glide.getContext().getApplicationContext().unregisterComponentCallbacks(glide);
219+
glide.unregisterActivityLifecycleCallbacks();
209220
glide.engine.shutdown();
210221
}
211222
glide = null;
@@ -265,6 +276,7 @@ private static void initializeGlide(
265276
}
266277
Glide glide = builder.build(applicationContext, manifestModules, annotationGeneratedModule);
267278
applicationContext.registerComponentCallbacks(glide);
279+
glide.registerActivityLifecycleCallbacks();
268280
Glide.glide = glide;
269281
}
270282

@@ -332,6 +344,12 @@ private static void throwIncorrectGlideModule(Exception e) {
332344
this.connectivityMonitorFactory = connectivityMonitorFactory;
333345
this.defaultRequestOptionsFactory = defaultRequestOptionsFactory;
334346

347+
GlideBuilder.MemoryCategoryInBackground memoryCategoryInBackground =
348+
experiments.get(GlideBuilder.MemoryCategoryInBackground.class);
349+
if (memoryCategoryInBackground != null) {
350+
this.memoryCategoryInBackground = memoryCategoryInBackground.value();
351+
}
352+
335353
// This has a circular relationship with Glide and GlideContext in that it depends on both,
336354
// but it's created by Glide's constructor. In practice this shouldn't matter because the
337355
// supplier holding the registry should never be initialized before this constructor finishes.
@@ -678,6 +696,11 @@ void unregisterRequestManager(RequestManager requestManager) {
678696
@Override
679697
public void onTrimMemory(int level) {
680698
trimMemory(level);
699+
// when level is TRIM_MEMORY_UI_HIDDEN or higher, it indicates that the app is
700+
// in the background, limit the memory usage by memoryCategoryInBackground.
701+
if (level >= TRIM_MEMORY_UI_HIDDEN) {
702+
setMemoryCategoryWhenInBackground();
703+
}
681704
}
682705

683706
@Override
@@ -697,4 +720,85 @@ public interface RequestOptionsFactory {
697720
@NonNull
698721
RequestOptions build();
699722
}
723+
724+
private void registerActivityLifecycleCallbacks() {
725+
if (memoryCategoryInBackground != null) {
726+
Context context = getContext().getApplicationContext();
727+
if (!(context instanceof Application) && Log.isLoggable(TAG, Log.WARN)) {
728+
Log.w(
729+
TAG,
730+
"Glide requires an Application Context. You passed: "
731+
+ context
732+
+ ". This will disable setting memory category in background.");
733+
return;
734+
}
735+
((Application) context).registerActivityLifecycleCallbacks(setMemoryCategoryCallbacks.get());
736+
}
737+
}
738+
739+
private void unregisterActivityLifecycleCallbacks() {
740+
if (memoryCategoryInBackground != null) {
741+
Context context = getContext().getApplicationContext();
742+
if (context instanceof Application) {
743+
((Application) context)
744+
.unregisterActivityLifecycleCallbacks(setMemoryCategoryCallbacks.get());
745+
}
746+
}
747+
}
748+
749+
private void setMemoryCategoryWhenInBackground() {
750+
if (memoryCategoryInBackground == null || inBackground) {
751+
return;
752+
}
753+
inBackground = true;
754+
memoryCategoryInForeground = setMemoryCategory(memoryCategoryInBackground);
755+
}
756+
757+
private void setMemoryCategoryWhenInForeground() {
758+
if (memoryCategoryInBackground == null || !inBackground) {
759+
return;
760+
}
761+
inBackground = false;
762+
setMemoryCategory(memoryCategoryInForeground);
763+
}
764+
765+
private final class SetMemoryCategoryOnLifecycleCallbacks
766+
implements Application.ActivityLifecycleCallbacks {
767+
@Override
768+
public void onActivityStarted(Activity activity) {
769+
// Do nothing.
770+
}
771+
772+
@Override
773+
public void onActivityResumed(Activity activity) {
774+
// Any activity resumed indicates that the app is no longer in the background,
775+
// and we should restore the memory usage to normal.
776+
setMemoryCategoryWhenInForeground();
777+
}
778+
779+
@Override
780+
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
781+
// Do nothing.
782+
}
783+
784+
@Override
785+
public void onActivityDestroyed(Activity activity) {
786+
// Do nothing.
787+
}
788+
789+
@Override
790+
public void onActivityStopped(Activity activity) {
791+
// Do nothing.
792+
}
793+
794+
@Override
795+
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
796+
// Do nothing.
797+
}
798+
799+
@Override
800+
public void onActivityPaused(Activity activity) {
801+
// Do nothing.
802+
}
803+
}
700804
}

library/src/main/java/com/bumptech/glide/GlideBuilder.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,17 @@ public GlideBuilder setUseMediaStoreOpenFileApisIfPossible(boolean isEnabled) {
512512
return this;
513513
}
514514

515+
/**
516+
* Set to {@code true} to make Glide use {@link MemoryCategory} to set the memory category when
517+
* the app is in the background.
518+
*
519+
* <p>This is an experimental API that may be removed in the future.
520+
*/
521+
public GlideBuilder setMemoryCategoryInBackground(MemoryCategory memoryCategory) {
522+
glideExperimentsBuilder.add(new MemoryCategoryInBackground(memoryCategory));
523+
return this;
524+
}
525+
515526
/**
516527
* @deprecated This method does nothing. It will be hard coded and removed in a future release
517528
* without further warning.
@@ -653,4 +664,17 @@ public static final class OverrideGlideThreadPriority implements Experiment {}
653664

654665
/** See {@link #setUseMediaStoreOpenFileApisIfPossible(boolean)}. */
655666
public static final class UseMediaStoreOpenFileApisIfPossible implements Experiment {}
667+
668+
/** See {@link #setMemoryCategoryInBackground(MemoryCategory)} */
669+
public static final class MemoryCategoryInBackground implements Experiment {
670+
private final MemoryCategory memoryCategory;
671+
672+
MemoryCategoryInBackground(MemoryCategory memoryCategory) {
673+
this.memoryCategory = memoryCategory;
674+
}
675+
676+
public MemoryCategory value() {
677+
return memoryCategory;
678+
}
679+
}
656680
}

library/src/main/java/com/bumptech/glide/MemoryCategory.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
/** An enum for dynamically modifying the amount of memory Glide is able to use. */
44
public enum MemoryCategory {
5+
/** Tells Glide's memory cache and bitmap pool to use no memory. */
6+
ZERO(0f),
57
/**
68
* Tells Glide's memory cache and bitmap pool to use at most half of their initial maximum size.
79
*/

0 commit comments

Comments
 (0)