11package com .bumptech .glide ;
22
33import android .app .Activity ;
4+ import android .app .Application ;
45import android .content .ComponentCallbacks2 ;
56import android .content .Context ;
67import android .content .res .Configuration ;
78import android .graphics .Bitmap ;
9+ import android .os .Bundle ;
810import android .os .MessageQueue .IdleHandler ;
911import android .util .Log ;
1012import android .view .View ;
3335import com .bumptech .glide .request .RequestOptions ;
3436import com .bumptech .glide .request .target .ImageViewTargetFactory ;
3537import com .bumptech .glide .request .target .Target ;
38+ import com .bumptech .glide .util .GlideSuppliers ;
3639import com .bumptech .glide .util .GlideSuppliers .GlideSupplier ;
3740import com .bumptech .glide .util .Preconditions ;
3841import 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.
@@ -205,7 +215,9 @@ public static void enableHardwareBitmaps() {
205215 public static void tearDown () {
206216 synchronized (Glide .class ) {
207217 if (glide != null ) {
208- glide .getContext ().getApplicationContext ().unregisterComponentCallbacks (glide );
218+ Application application = (Application ) glide .getContext ().getApplicationContext ();
219+ application .unregisterComponentCallbacks (glide );
220+ glide .unregisterActivityLifecycleCallbacks ();
209221 glide .engine .shutdown ();
210222 }
211223 glide = null ;
@@ -224,7 +236,7 @@ private static void initializeGlide(
224236 @ NonNull Context context ,
225237 @ NonNull GlideBuilder builder ,
226238 @ Nullable GeneratedAppGlideModule annotationGeneratedModule ) {
227- Context applicationContext = context .getApplicationContext ();
239+ Application applicationContext = ( Application ) context .getApplicationContext ();
228240 List <GlideModule > manifestModules = Collections .emptyList ();
229241 if (annotationGeneratedModule == null || annotationGeneratedModule .isManifestParsingEnabled ()) {
230242 manifestModules = new ManifestParser (applicationContext ).parse ();
@@ -265,6 +277,7 @@ private static void initializeGlide(
265277 }
266278 Glide glide = builder .build (applicationContext , manifestModules , annotationGeneratedModule );
267279 applicationContext .registerComponentCallbacks (glide );
280+ glide .registerActivityLifecycleCallbacks ();
268281 Glide .glide = glide ;
269282 }
270283
@@ -332,6 +345,12 @@ private static void throwIncorrectGlideModule(Exception e) {
332345 this .connectivityMonitorFactory = connectivityMonitorFactory ;
333346 this .defaultRequestOptionsFactory = defaultRequestOptionsFactory ;
334347
348+ GlideBuilder .MemoryCategoryInBackground memoryCategoryInBackground =
349+ experiments .get (GlideBuilder .MemoryCategoryInBackground .class );
350+ if (memoryCategoryInBackground != null ) {
351+ this .memoryCategoryInBackground = memoryCategoryInBackground .value ();
352+ }
353+
335354 // This has a circular relationship with Glide and GlideContext in that it depends on both,
336355 // but it's created by Glide's constructor. In practice this shouldn't matter because the
337356 // supplier holding the registry should never be initialized before this constructor finishes.
@@ -354,6 +373,20 @@ private static void throwIncorrectGlideModule(Exception e) {
354373 logLevel );
355374 }
356375
376+ private void registerActivityLifecycleCallbacks () {
377+ if (memoryCategoryInBackground != null ) {
378+ Application context = (Application ) getContext ().getApplicationContext ();
379+ context .registerActivityLifecycleCallbacks (setMemoryCategoryCallbacks .get ());
380+ }
381+ }
382+
383+ private void unregisterActivityLifecycleCallbacks () {
384+ if (memoryCategoryInBackground != null ) {
385+ Application context = (Application ) getContext ().getApplicationContext ();
386+ context .unregisterActivityLifecycleCallbacks (setMemoryCategoryCallbacks .get ());
387+ }
388+ }
389+
357390 /**
358391 * Returns the {@link com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool} used to
359392 * temporarily store {@link android.graphics.Bitmap}s so they can be reused to avoid garbage
@@ -675,9 +708,30 @@ void unregisterRequestManager(RequestManager requestManager) {
675708 }
676709 }
677710
711+ private void setMemoryCategoryWhenInBackground () {
712+ if (memoryCategoryInBackground == null || inBackground ) {
713+ return ;
714+ }
715+ inBackground = true ;
716+ memoryCategoryInForeground = setMemoryCategory (memoryCategoryInBackground );
717+ }
718+
719+ private void setMemoryCategoryWhenInForeground () {
720+ if (memoryCategoryInBackground == null || !inBackground ) {
721+ return ;
722+ }
723+ inBackground = false ;
724+ setMemoryCategory (memoryCategoryInForeground );
725+ }
726+
678727 @ Override
679728 public void onTrimMemory (int level ) {
680729 trimMemory (level );
730+ // when level is TRIM_MEMORY_UI_HIDDEN or higher, it indicates that the app is
731+ // in the background, limit the memory usage by memoryCategoryInBackground.
732+ if (level >= TRIM_MEMORY_UI_HIDDEN ) {
733+ setMemoryCategoryWhenInBackground ();
734+ }
681735 }
682736
683737 @ Override
@@ -697,4 +751,44 @@ public interface RequestOptionsFactory {
697751 @ NonNull
698752 RequestOptions build ();
699753 }
754+
755+ private final class SetMemoryCategoryOnLifecycleCallbacks
756+ implements Application .ActivityLifecycleCallbacks {
757+ @ Override
758+ public void onActivityStarted (Activity activity ) {
759+ // Do nothing.
760+ }
761+
762+ @ Override
763+ public void onActivityResumed (Activity activity ) {
764+ // Any activity resumed indicates that the app is no longer in the background,
765+ // and we should restore the memory usage to normal.
766+ setMemoryCategoryWhenInForeground ();
767+ }
768+
769+ @ Override
770+ public void onActivityCreated (Activity activity , Bundle savedInstanceState ) {
771+ // Do nothing.
772+ }
773+
774+ @ Override
775+ public void onActivityDestroyed (Activity activity ) {
776+ // Do nothing.
777+ }
778+
779+ @ Override
780+ public void onActivityStopped (Activity activity ) {
781+ // Do nothing.
782+ }
783+
784+ @ Override
785+ public void onActivitySaveInstanceState (Activity activity , Bundle outState ) {
786+ // Do nothing.
787+ }
788+
789+ @ Override
790+ public void onActivityPaused (Activity activity ) {
791+ // Do nothing.
792+ }
793+ }
700794}
0 commit comments