-
Notifications
You must be signed in to change notification settings - Fork 6.1k
/
Glide.java
688 lines (630 loc) · 26.4 KB
/
Glide.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
package com.bumptech.glide;
import android.app.Activity;
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.os.MessageQueue.IdleHandler;
import android.util.Log;
import android.view.View;
import androidx.annotation.GuardedBy;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import com.bumptech.glide.GlideBuilder.EnableLazyGlideRegistry;
import com.bumptech.glide.load.DecodeFormat;
import com.bumptech.glide.load.engine.Engine;
import com.bumptech.glide.load.engine.bitmap_recycle.ArrayPool;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.engine.cache.MemoryCache;
import com.bumptech.glide.load.engine.prefill.BitmapPreFiller;
import com.bumptech.glide.load.engine.prefill.PreFillType;
import com.bumptech.glide.load.engine.prefill.PreFillType.Builder;
import com.bumptech.glide.load.resource.bitmap.Downsampler;
import com.bumptech.glide.load.resource.bitmap.HardwareConfigState;
import com.bumptech.glide.manager.ConnectivityMonitorFactory;
import com.bumptech.glide.manager.RequestManagerRetriever;
import com.bumptech.glide.module.AppGlideModule;
import com.bumptech.glide.module.GlideModule;
import com.bumptech.glide.module.ManifestParser;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.ImageViewTargetFactory;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.util.GlideSuppliers.GlideSupplier;
import com.bumptech.glide.util.Preconditions;
import com.bumptech.glide.util.Util;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* A singleton to present a simple static interface for building requests with {@link
* RequestBuilder} and maintaining an {@link Engine}, {@link BitmapPool}, {@link
* com.bumptech.glide.load.engine.cache.DiskCache} and {@link MemoryCache}.
*/
public class Glide implements ComponentCallbacks2 {
private static final String DEFAULT_DISK_CACHE_DIR = "image_manager_disk_cache";
private static final String TAG = "Glide";
@GuardedBy("Glide.class")
private static volatile Glide glide;
private static volatile boolean isInitializing;
private final Engine engine;
private final BitmapPool bitmapPool;
private final MemoryCache memoryCache;
private final GlideContext glideContext;
private final ArrayPool arrayPool;
private final RequestManagerRetriever requestManagerRetriever;
private final ConnectivityMonitorFactory connectivityMonitorFactory;
@GuardedBy("managers")
private final List<RequestManager> managers = new ArrayList<>();
private final RequestOptionsFactory defaultRequestOptionsFactory;
private MemoryCategory memoryCategory = MemoryCategory.NORMAL;
@GuardedBy("this")
@Nullable
private BitmapPreFiller bitmapPreFiller;
/**
* Returns a directory with a default name in the private cache directory of the application to
* use to store retrieved media and thumbnails.
*
* @param context A context.
* @see #getPhotoCacheDir(android.content.Context, String)
*/
@Nullable
public static File getPhotoCacheDir(@NonNull Context context) {
return getPhotoCacheDir(context, DEFAULT_DISK_CACHE_DIR);
}
/**
* Returns a directory with the given name in the private cache directory of the application to
* use to store retrieved media and thumbnails.
*
* @param context A context.
* @param cacheName The name of the subdirectory in which to store the cache.
* @see #getPhotoCacheDir(android.content.Context)
*/
@Nullable
public static File getPhotoCacheDir(@NonNull Context context, @NonNull String cacheName) {
File cacheDir = context.getCacheDir();
if (cacheDir != null) {
File result = new File(cacheDir, cacheName);
if (result.isDirectory() || result.mkdirs()) {
return result;
}
// File wasn't able to create a directory, or the result exists but not a directory
return null;
}
if (Log.isLoggable(TAG, Log.ERROR)) {
Log.e(TAG, "default disk cache dir is null");
}
return null;
}
/**
* Get the singleton.
*
* @return the singleton
*/
@NonNull
// Double checked locking is safe here.
@SuppressWarnings("GuardedBy")
public static Glide get(@NonNull Context context) {
if (glide == null) {
GeneratedAppGlideModule annotationGeneratedModule =
getAnnotationGeneratedGlideModules(context.getApplicationContext());
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context, annotationGeneratedModule);
}
}
}
return glide;
}
@GuardedBy("Glide.class")
private static void checkAndInitializeGlide(
@NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) {
// In the thread running initGlide(), one or more classes may call Glide.get(context).
// Without this check, those calls could trigger infinite recursion.
if (isInitializing) {
throw new IllegalStateException(
"You cannot call Glide.get() in registerComponents(),"
+ " use the provided Glide instance instead");
}
isInitializing = true;
initializeGlide(context, generatedAppGlideModule);
isInitializing = false;
}
/**
* @deprecated Use {@link #init(Context, GlideBuilder)} to get a singleton compatible with Glide's
* generated API.
* <p>This method will be removed in a future version of Glide.
*/
@VisibleForTesting
@Deprecated
public static synchronized void init(Glide glide) {
if (Glide.glide != null) {
tearDown();
}
Glide.glide = glide;
}
@VisibleForTesting
public static void init(@NonNull Context context, @NonNull GlideBuilder builder) {
GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules(context);
synchronized (Glide.class) {
if (Glide.glide != null) {
tearDown();
}
initializeGlide(context, builder, annotationGeneratedModule);
}
}
/**
* Allows hardware Bitmaps to be used prior to the first frame in the app being drawn as soon as
* this method is called.
*
* <p>If you use this method in non-test code, your app will experience native crashes on some
* versions of Android if you try to decode a hardware Bitmap. This method is only useful for
* testing.
*/
@VisibleForTesting
public static void enableHardwareBitmaps() {
HardwareConfigState.getInstance().unblockHardwareBitmaps();
}
@VisibleForTesting
public static void tearDown() {
synchronized (Glide.class) {
if (glide != null) {
glide.getContext().getApplicationContext().unregisterComponentCallbacks(glide);
glide.engine.shutdown();
}
glide = null;
}
}
@GuardedBy("Glide.class")
private static void initializeGlide(
@NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) {
initializeGlide(context, new GlideBuilder(), generatedAppGlideModule);
}
@GuardedBy("Glide.class")
@SuppressWarnings("deprecation")
private static void initializeGlide(
@NonNull Context context,
@NonNull GlideBuilder builder,
@Nullable GeneratedAppGlideModule annotationGeneratedModule) {
Context applicationContext = context.getApplicationContext();
List<GlideModule> manifestModules = Collections.emptyList();
if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
manifestModules = new ManifestParser(applicationContext).parse();
}
if (annotationGeneratedModule != null
&& !annotationGeneratedModule.getExcludedModuleClasses().isEmpty()) {
Set<Class<?>> excludedModuleClasses = annotationGeneratedModule.getExcludedModuleClasses();
Iterator<GlideModule> iterator = manifestModules.iterator();
while (iterator.hasNext()) {
GlideModule current = iterator.next();
if (!excludedModuleClasses.contains(current.getClass())) {
continue;
}
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "AppGlideModule excludes manifest GlideModule: " + current);
}
iterator.remove();
}
}
if (Log.isLoggable(TAG, Log.DEBUG)) {
for (GlideModule glideModule : manifestModules) {
Log.d(TAG, "Discovered GlideModule from manifest: " + glideModule.getClass());
}
}
RequestManagerRetriever.RequestManagerFactory factory =
annotationGeneratedModule != null
? annotationGeneratedModule.getRequestManagerFactory()
: null;
builder.setRequestManagerFactory(factory);
for (GlideModule module : manifestModules) {
module.applyOptions(applicationContext, builder);
}
if (annotationGeneratedModule != null) {
annotationGeneratedModule.applyOptions(applicationContext, builder);
}
Glide glide = builder.build(applicationContext, manifestModules, annotationGeneratedModule);
applicationContext.registerComponentCallbacks(glide);
// Trigger the registry initialization eagerly, similar to the codepath prior to the experiment.
if (!glide.getGlideContext().getExperiments().isEnabled(EnableLazyGlideRegistry.class)) {
glide.getGlideContext().getRegistry();
}
Glide.glide = glide;
}
@Nullable
@SuppressWarnings({"unchecked", "TryWithIdenticalCatches", "PMD.UnusedFormalParameter"})
private static GeneratedAppGlideModule getAnnotationGeneratedGlideModules(Context context) {
GeneratedAppGlideModule result = null;
try {
Class<GeneratedAppGlideModule> clazz =
(Class<GeneratedAppGlideModule>)
Class.forName("com.bumptech.glide.GeneratedAppGlideModuleImpl");
result =
clazz.getDeclaredConstructor(Context.class).newInstance(context.getApplicationContext());
} catch (ClassNotFoundException e) {
if (Log.isLoggable(TAG, Log.WARN)) {
Log.w(
TAG,
"Failed to find GeneratedAppGlideModule. You should include an"
+ " annotationProcessor compile dependency on com.github.bumptech.glide:compiler"
+ " in your application and a @GlideModule annotated AppGlideModule implementation"
+ " or LibraryGlideModules will be silently ignored");
}
// These exceptions can't be squashed across all versions of Android.
} catch (InstantiationException e) {
throwIncorrectGlideModule(e);
} catch (IllegalAccessException e) {
throwIncorrectGlideModule(e);
} catch (NoSuchMethodException e) {
throwIncorrectGlideModule(e);
} catch (InvocationTargetException e) {
throwIncorrectGlideModule(e);
}
return result;
}
private static void throwIncorrectGlideModule(Exception e) {
throw new IllegalStateException(
"GeneratedAppGlideModuleImpl is implemented incorrectly."
+ " If you've manually implemented this class, remove your implementation. The"
+ " Annotation processor will generate a correct implementation.",
e);
}
@SuppressWarnings("PMD.UnusedFormalParameter")
Glide(
@NonNull Context context,
@NonNull Engine engine,
@NonNull MemoryCache memoryCache,
@NonNull BitmapPool bitmapPool,
@NonNull ArrayPool arrayPool,
@NonNull RequestManagerRetriever requestManagerRetriever,
@NonNull ConnectivityMonitorFactory connectivityMonitorFactory,
int logLevel,
@NonNull RequestOptionsFactory defaultRequestOptionsFactory,
@NonNull Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions,
@NonNull List<RequestListener<Object>> defaultRequestListeners,
@NonNull List<GlideModule> manifestModules,
@Nullable AppGlideModule annotationGeneratedModule,
@NonNull GlideExperiments experiments) {
this.engine = engine;
this.bitmapPool = bitmapPool;
this.arrayPool = arrayPool;
this.memoryCache = memoryCache;
this.requestManagerRetriever = requestManagerRetriever;
this.connectivityMonitorFactory = connectivityMonitorFactory;
this.defaultRequestOptionsFactory = defaultRequestOptionsFactory;
// This has a circular relationship with Glide and GlideContext in that it depends on both,
// but it's created by Glide's constructor. In practice this shouldn't matter because the
// supplier holding the registry should never be initialized before this constructor finishes.
GlideSupplier<Registry> registry =
RegistryFactory.lazilyCreateAndInitializeRegistry(
this, manifestModules, annotationGeneratedModule);
ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory();
glideContext =
new GlideContext(
context,
arrayPool,
registry,
imageViewTargetFactory,
defaultRequestOptionsFactory,
defaultTransitionOptions,
defaultRequestListeners,
engine,
experiments,
logLevel);
}
/**
* Returns the {@link com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool} used to
* temporarily store {@link android.graphics.Bitmap}s so they can be reused to avoid garbage
* collections.
*
* <p>Note - Using this pool directly can lead to undefined behavior and strange drawing errors.
* Any {@link android.graphics.Bitmap} added to the pool must not be currently in use in any other
* part of the application. Any {@link android.graphics.Bitmap} added to the pool must be removed
* from the pool before it is added a second time.
*
* <p>Note - To make effective use of the pool, any {@link android.graphics.Bitmap} removed from
* the pool must eventually be re-added. Otherwise the pool will eventually empty and will not
* serve any useful purpose.
*
* <p>The primary reason this object is exposed is for use in custom {@link
* com.bumptech.glide.load.ResourceDecoder}s and {@link com.bumptech.glide.load.Transformation}s.
* Use outside of these classes is not generally recommended.
*/
@NonNull
public BitmapPool getBitmapPool() {
return bitmapPool;
}
@NonNull
public ArrayPool getArrayPool() {
return arrayPool;
}
/**
* @return The context associated with this instance.
*/
@NonNull
public Context getContext() {
return glideContext.getBaseContext();
}
ConnectivityMonitorFactory getConnectivityMonitorFactory() {
return connectivityMonitorFactory;
}
@NonNull
GlideContext getGlideContext() {
return glideContext;
}
/**
* Pre-fills the {@link BitmapPool} using the given sizes.
*
* <p>Enough Bitmaps are added to completely fill the pool, so most or all of the Bitmaps
* currently in the pool will be evicted. Bitmaps are allocated according to the weights of the
* given sizes, where each size gets (weight / prefillWeightSum) percent of the pool to fill.
*
* <p>Note - Pre-filling is done asynchronously using and {@link IdleHandler}. Any currently
* running pre-fill will be cancelled and replaced by a call to this method.
*
* <p>This method should be used with caution, overly aggressive pre-filling is substantially
* worse than not pre-filling at all. Pre-filling should only be started in onCreate to avoid
* constantly clearing and re-filling the {@link BitmapPool}. Rotation should be carefully
* considered as well. It may be worth calling this method only when no saved instance state
* exists so that pre-filling only happens when the Activity is first created, rather than on
* every rotation.
*
* @param bitmapAttributeBuilders The list of {@link Builder Builders} representing individual
* sizes and configurations of {@link Bitmap}s to be pre-filled.
*/
@SuppressWarnings("unused") // Public API
public synchronized void preFillBitmapPool(
@NonNull PreFillType.Builder... bitmapAttributeBuilders) {
if (bitmapPreFiller == null) {
DecodeFormat decodeFormat =
defaultRequestOptionsFactory.build().getOptions().get(Downsampler.DECODE_FORMAT);
bitmapPreFiller = new BitmapPreFiller(memoryCache, bitmapPool, decodeFormat);
}
bitmapPreFiller.preFill(bitmapAttributeBuilders);
}
/**
* Clears as much memory as possible.
*
* @see android.content.ComponentCallbacks#onLowMemory()
* @see android.content.ComponentCallbacks2#onLowMemory()
*/
public void clearMemory() {
// Engine asserts this anyway when removing resources, fail faster and consistently
Util.assertMainThread();
// memory cache needs to be cleared before bitmap pool to clear re-pooled Bitmaps too. See #687.
memoryCache.clearMemory();
bitmapPool.clearMemory();
arrayPool.clearMemory();
}
/**
* Clears some memory with the exact amount depending on the given level.
*
* @see android.content.ComponentCallbacks2#onTrimMemory(int)
*/
public void trimMemory(int level) {
// Engine asserts this anyway when removing resources, fail faster and consistently
Util.assertMainThread();
// Request managers need to be trimmed before the caches and pools, in order for the latter to
// have the most benefit.
synchronized (managers) {
for (RequestManager manager : managers) {
manager.onTrimMemory(level);
}
}
// memory cache needs to be trimmed before bitmap pool to trim re-pooled Bitmaps too. See #687.
memoryCache.trimMemory(level);
bitmapPool.trimMemory(level);
arrayPool.trimMemory(level);
}
/**
* Clears disk cache.
*
* <p>This method should always be called on a background thread, since it is a blocking call.
*/
// Public API.
@SuppressWarnings({"unused", "WeakerAccess"})
public void clearDiskCache() {
Util.assertBackgroundThread();
engine.clearDiskCache();
}
/** Internal method. */
@NonNull
public RequestManagerRetriever getRequestManagerRetriever() {
return requestManagerRetriever;
}
/**
* Adjusts Glide's current and maximum memory usage based on the given {@link MemoryCategory}.
*
* <p>The default {@link MemoryCategory} is {@link MemoryCategory#NORMAL}. {@link
* MemoryCategory#HIGH} increases Glide's maximum memory usage by up to 50% and {@link
* MemoryCategory#LOW} decreases Glide's maximum memory usage by 50%. This method should be used
* to temporarily increase or decrease memory usage for a single Activity or part of the app. Use
* {@link GlideBuilder#setMemoryCache(MemoryCache)} to put a permanent memory size if you want to
* change the default.
*
* @return the previous MemoryCategory used by Glide.
*/
@SuppressWarnings("WeakerAccess") // Public API
@NonNull
public MemoryCategory setMemoryCategory(@NonNull MemoryCategory memoryCategory) {
// Engine asserts this anyway when removing resources, fail faster and consistently
Util.assertMainThread();
// memory cache needs to be trimmed before bitmap pool to trim re-pooled Bitmaps too. See #687.
memoryCache.setSizeMultiplier(memoryCategory.getMultiplier());
bitmapPool.setSizeMultiplier(memoryCategory.getMultiplier());
MemoryCategory oldCategory = this.memoryCategory;
this.memoryCategory = memoryCategory;
return oldCategory;
}
@NonNull
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
// Context could be null for other reasons (ie the user passes in null), but in practice it will
// only occur due to errors with the Fragment lifecycle.
Preconditions.checkNotNull(
context,
"You cannot start a load on a not yet attached View or a Fragment where getActivity() "
+ "returns null (which usually occurs when getActivity() is called before the Fragment "
+ "is attached or after the Fragment is destroyed).");
return Glide.get(context).getRequestManagerRetriever();
}
/**
* Begin a load with Glide by passing in a context.
*
* <p>Any requests started using a context will only have the application level options applied
* and will not be started or stopped based on lifecycle events. In general, loads should be
* started at the level the result will be used in. If the resource will be used in a view in a
* child fragment, the load should be started with {@link #with(android.app.Fragment)}} using that
* child fragment. Similarly, if the resource will be used in a view in the parent fragment, the
* load should be started with {@link #with(android.app.Fragment)} using the parent fragment. In
* the same vein, if the resource will be used in a view in an activity, the load should be
* started with {@link #with(android.app.Activity)}}.
*
* <p>This method is appropriate for resources that will be used outside of the normal fragment or
* activity lifecycle (For example in services, or for notification thumbnails).
*
* @param context Any context, will not be retained.
* @return A RequestManager for the top level application that can be used to start a load.
* @see #with(android.app.Activity)
* @see #with(android.app.Fragment)
* @see #with(androidx.fragment.app.Fragment)
* @see #with(androidx.fragment.app.FragmentActivity)
*/
@NonNull
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context);
}
/**
* Begin a load with Glide that will be tied to the given {@link android.app.Activity}'s lifecycle
* and that uses the given {@link Activity}'s default options.
*
* @param activity The activity to use.
* @return A RequestManager for the given activity that can be used to start a load.
*/
@NonNull
public static RequestManager with(@NonNull Activity activity) {
return getRetriever(activity).get(activity);
}
/**
* Begin a load with Glide that will tied to the give {@link
* androidx.fragment.app.FragmentActivity}'s lifecycle and that uses the given {@link
* androidx.fragment.app.FragmentActivity}'s default options.
*
* @param activity The activity to use.
* @return A RequestManager for the given FragmentActivity that can be used to start a load.
*/
@NonNull
public static RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
/**
* Begin a load with Glide that will be tied to the given {@link androidx.fragment.app.Fragment}'s
* lifecycle and that uses the given {@link androidx.fragment.app.Fragment}'s default options.
*
* @param fragment The fragment to use.
* @return A RequestManager for the given Fragment that can be used to start a load.
*/
@NonNull
public static RequestManager with(@NonNull Fragment fragment) {
return getRetriever(fragment.getContext()).get(fragment);
}
/**
* Begin a load with Glide that will be tied to the given {@link android.app.Fragment}'s lifecycle
* and that uses the given {@link android.app.Fragment}'s default options.
*
* @param fragment The fragment to use.
* @return A RequestManager for the given Fragment that can be used to start a load.
* @deprecated Prefer support Fragments and {@link #with(Fragment)} instead, {@link
* android.app.Fragment} will be deprecated. See
* https://github.com/android/android-ktx/pull/161#issuecomment-363270555.
*/
@SuppressWarnings("deprecation")
@Deprecated
@NonNull
public static RequestManager with(@NonNull android.app.Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
/**
* Begin a load with Glide that will be tied to the lifecycle of the {@link Fragment}, {@link
* android.app.Fragment}, or {@link Activity} that contains the View.
*
* <p>A {@link Fragment} or {@link android.app.Fragment} is assumed to contain a View if the View
* is a child of the View returned by the {@link Fragment#getView()}} method.
*
* <p>This method will not work if the View is not attached. Prefer the Activity and Fragment
* variants unless you're loading in a View subclass.
*
* <p>This method may be inefficient aways and is definitely inefficient for large hierarchies.
* Consider memoizing the result after the View is attached or again, prefer the Activity and
* Fragment variants whenever possible.
*
* <p>When used in Applications that use the non-support {@link android.app.Fragment} classes,
* calling this method will produce noisy logs from {@link android.app.FragmentManager}. Consider
* avoiding entirely or using the {@link Fragment}s from the support library instead.
*
* <p>If the support {@link FragmentActivity} class is used, this method will only attempt to
* discover support {@link Fragment}s. Any non-support {@link android.app.Fragment}s attached to
* the {@link FragmentActivity} will be ignored.
*
* @param view The view to search for a containing Fragment or Activity from.
* @return A RequestManager that can be used to start a load.
*/
@NonNull
public static RequestManager with(@NonNull View view) {
return getRetriever(view.getContext()).get(view);
}
@NonNull
public Registry getRegistry() {
return glideContext.getRegistry();
}
boolean removeFromManagers(@NonNull Target<?> target) {
synchronized (managers) {
for (RequestManager requestManager : managers) {
if (requestManager.untrack(target)) {
return true;
}
}
}
return false;
}
void registerRequestManager(RequestManager requestManager) {
synchronized (managers) {
if (managers.contains(requestManager)) {
throw new IllegalStateException("Cannot register already registered manager");
}
managers.add(requestManager);
}
}
void unregisterRequestManager(RequestManager requestManager) {
synchronized (managers) {
if (!managers.contains(requestManager)) {
throw new IllegalStateException("Cannot unregister not yet registered manager");
}
managers.remove(requestManager);
}
}
@Override
public void onTrimMemory(int level) {
trimMemory(level);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
// Do nothing.
}
@Override
public void onLowMemory() {
clearMemory();
}
/** Creates a new instance of {@link RequestOptions}. */
public interface RequestOptionsFactory {
/** Returns a non-null {@link RequestOptions} object. */
@NonNull
RequestOptions build();
}
}