Glide4|Glide4 源码解析和原理
glide 4.8.0
1、with 方法
public static GlideRequests with(@NonNull Context context)
public static GlideRequests with(@NonNull Activity activity)
public static GlideRequests with(@NonNull FragmentActivity activity)
public static GlideRequests with(@NonNull Fragment fragment)
public static GlideRequests with(@NonNull android.app.Fragment fragment)
public static GlideRequests with(@NonNull View view)
初始化initializeGlide,获取使用注解定义的AppGlideModule 和 清单文件中配置的AppGlideModule
private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
Context applicationContext = context.getApplicationContext();
//获取使用注解自定义的AppGlideModule
GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
//Collections.emptyList()返回一个空的List, Collections类的一个静态内部类,
//它继承AbstractList后并没有实现add()、remove()等方法,因此这个返回值List并不能增加删除元素
//这个方法主要目的就是返回一个不可变的列表,使用这个方法作为返回值就不需要再创建一个新对象,可以减少内存开销。
//并且返回一个size为0的List,调用者不需要校验返回值是否为null,所以建议使用这个方法返回可能为空的List。
//如果想 new 一个空的 List ,而这个 List 以后也不会再添加元素,那么就用 Collections.emptyList()
List manifestModules = Collections.emptyList();
//获取在manifest文件中配置的AppGlideModule
if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
manifestModules = new ManifestParser(applicationContext).parse();
}if (annotationGeneratedModule != null
&& !annotationGeneratedModule.getExcludedModuleClasses().isEmpty()) {
Set> excludedModuleClasses =
annotationGeneratedModule.getExcludedModuleClasses();
Iterator iterator = manifestModules.iterator();
while (iterator.hasNext()) {
com.bumptech.glide.module.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 (com.bumptech.glide.module.GlideModule glideModule : manifestModules) {
Log.d(TAG, "Discovered GlideModule from manifest: " + glideModule.getClass());
}
}RequestManagerRetriever.RequestManagerFactory factory =
annotationGeneratedModule != null
? annotationGeneratedModule.getRequestManagerFactory() : null;
builder.setRequestManagerFactory(factory);
for (com.bumptech.glide.module.GlideModule module : manifestModules) {
module.applyOptions(applicationContext, builder);
}
if (annotationGeneratedModule != null) {
annotationGeneratedModule.applyOptions(applicationContext, builder);
}
//创建glide实例
Glide glide = builder.build(applicationContext);
for (com.bumptech.glide.module.GlideModule module : manifestModules) {
module.registerComponents(applicationContext, glide, glide.registry);
}
//RegistersComponents 用来注册 Glide 中一些组件的
//Registry 对象,这是用来管理注册 ModelLoader、Encoder、Decoder 等等
if (annotationGeneratedModule != null) {
annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
}
applicationContext.registerComponentCallbacks(glide);
Glide.glide = glide;
}
【Glide4|Glide4 源码解析和原理】GlideBuilder 是用来创建 Glide 实例的类,创建各种线程池内存缓存磁盘缓存图片加载引擎等
Glide build(@NonNull Context context) {
//创建加载图片线程池
if (sourceExecutor == null) {
sourceExecutor = GlideExecutor.newSourceExecutor();
}
//创建文件缓存线程池
if (diskCacheExecutor == null) {
diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
}
//创建加载图片动画线程池
if (animationExecutor == null) {
animationExecutor = GlideExecutor.newAnimationExecutor();
}
//根据设备获取相应的缓存大小
if (memorySizeCalculator == null) {
memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
}
//判断是否获取了网络请求权限
if (connectivityMonitorFactory == null) {
connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
}
//获取内存缓存图片池
if (bitmapPool == null) {
int size = memorySizeCalculator.getBitmapPoolSize();
if (size > 0) {
bitmapPool = new LruBitmapPool(size);
} else {
bitmapPool = new BitmapPoolAdapter();
}
}
//对象池
if (arrayPool == null) {
arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
}
//内存缓存
if (memoryCache == null) {
memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
}
//磁盘缓存工厂类
if (diskCacheFactory == null) {
diskCacheFactory = new InternalCacheDiskCacheFactory(context);
}
//加载图片引擎
if (engine == null) {
engine =
new Engine(
memoryCache,
diskCacheFactory,
diskCacheExecutor,
sourceExecutor,
GlideExecutor.newUnlimitedSourceExecutor(),
GlideExecutor.newAnimationExecutor(),
isActiveResourceRetentionAllowed);
}RequestManagerRetriever requestManagerRetriever =
new RequestManagerRetriever(requestManagerFactory);
return new Glide(
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptions.lock(),
defaultTransitionOptions);
}
new Glide
Encoder 是个接口,在 Glide 中也是个很重要的概念,用来将给定的数据写入持久性存储介质中(文件)
ResourceDecoder与 Encoder 对应,数据解码器,用来将原始数据解码成相应的数据类型
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 RequestOptions defaultRequestOptions,
@NonNull Map, TransitionOptions, ?>> defaultTransitionOptions) {
this.engine = engine;
this.bitmapPool = bitmapPool;
this.arrayPool = arrayPool;
this.memoryCache = memoryCache;
this.requestManagerRetriever = requestManagerRetriever;
this.connectivityMonitorFactory = connectivityMonitorFactory;
//解码格式
DecodeFormat decodeFormat = defaultRequestOptions.getOptions().get(Downsampler.DECODE_FORMAT);
bitmapPreFiller = new BitmapPreFiller(memoryCache, bitmapPool, decodeFormat);
final Resources resources = context.getResources();
registry = new Registry();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
registry.register(new ExifInterfaceImageHeaderParser());
}
//注册文件头解析类
registry.register(new DefaultImageHeaderParser());
Downsampler downsampler = new Downsampler(registry.getImageHeaderParsers(),
resources.getDisplayMetrics(), bitmapPool, arrayPool);
//解码类:将InputStream中解码成GIF
ByteBufferGifDecoder byteBufferGifDecoder =
new ByteBufferGifDecoder(context, registry.getImageHeaderParsers(), bitmapPool, arrayPool);
//解码类:将Video中解码成bitmap
ResourceDecoder parcelFileDescriptorVideoDecoder =
VideoDecoder.parcel(bitmapPool);
//解码类:将ByteBuffer解码成bitmap
ByteBufferBitmapDecoder byteBufferBitmapDecoder = new ByteBufferBitmapDecoder(downsampler);
//解码类:将InputStreams解码成bitmap
StreamBitmapDecoder streamBitmapDecoder = new StreamBitmapDecoder(downsampler, arrayPool);
//解码类:通过Uri解码成Drawable
ResourceDrawableDecoder resourceDrawableDecoder =
new ResourceDrawableDecoder(context);
//解码类:将资源文件转换成InputStream
ResourceLoader.StreamFactory resourceLoaderStreamFactory =
new ResourceLoader.StreamFactory(resources);
//将资源文件转换成URI
ResourceLoader.UriFactory resourceLoaderUriFactory =
new ResourceLoader.UriFactory(resources);
//将资源文件转换成ParcelFileDescriptor
ResourceLoader.FileDescriptorFactory resourceLoaderFileDescriptorFactory =
new ResourceLoader.FileDescriptorFactory(resources);
//将资源文件转换成ParcelFileDescriptor
ResourceLoader.AssetFileDescriptorFactory resourceLoaderAssetFileDescriptorFactory =
new ResourceLoader.AssetFileDescriptorFactory(resources);
//Bitmap解码类
BitmapEncoder bitmapEncoder = new BitmapEncoder(arrayPool);
//bitmap转btye[]类
BitmapBytesTranscoder bitmapBytesTranscoder = new BitmapBytesTranscoder();
//GifDrawable转btye[]类
GifDrawableBytesTranscoder gifDrawableBytesTranscoder = new GifDrawableBytesTranscoder();
ContentResolver contentResolver = context.getContentResolver();
registry
.append(ByteBuffer.class, new ByteBufferEncoder())
.append(InputStream.class, new StreamEncoder(arrayPool))
/* 添加转换成Bitmap相应解码类Bitmaps */
.append(Registry.BUCKET_BITMAP, ByteBuffer.class, Bitmap.class, byteBufferBitmapDecoder)
.append(Registry.BUCKET_BITMAP, InputStream.class, Bitmap.class, streamBitmapDecoder)
.append(
Registry.BUCKET_BITMAP,
ParcelFileDescriptor.class,
Bitmap.class,
parcelFileDescriptorVideoDecoder)
.append(
Registry.BUCKET_BITMAP,
AssetFileDescriptor.class,
Bitmap.class,
VideoDecoder.asset(bitmapPool))
.append(Bitmap.class, Bitmap.class, UnitModelLoader.Factory.getInstance())
.append(
Registry.BUCKET_BITMAP, Bitmap.class, Bitmap.class, new UnitBitmapDecoder())
.append(Bitmap.class, bitmapEncoder)
/* 添加转换成BitmapDrawables相应解码类 BitmapDrawables */
.append(
Registry.BUCKET_BITMAP_DRAWABLE,
ByteBuffer.class,
BitmapDrawable.class,
new BitmapDrawableDecoder<>(resources, byteBufferBitmapDecoder))
.append(
Registry.BUCKET_BITMAP_DRAWABLE,
InputStream.class,
BitmapDrawable.class,
new BitmapDrawableDecoder<>(resources, streamBitmapDecoder))
.append(
Registry.BUCKET_BITMAP_DRAWABLE,
ParcelFileDescriptor.class,
BitmapDrawable.class,
new BitmapDrawableDecoder<>(resources, parcelFileDescriptorVideoDecoder))
.append(BitmapDrawable.class, new BitmapDrawableEncoder(bitmapPool, bitmapEncoder))
/* 添加转换成GIFs相应解码类 GIFs */
.append(
Registry.BUCKET_GIF,
InputStream.class,
GifDrawable.class,
new StreamGifDecoder(registry.getImageHeaderParsers(), byteBufferGifDecoder, arrayPool))
.append(Registry.BUCKET_GIF, ByteBuffer.class, GifDrawable.class, byteBufferGifDecoder)
.append(GifDrawable.class, new GifDrawableEncoder())
/* GIF Frames */
// Compilation with Gradle requires the type to be specified for UnitModelLoader here.
.append(
GifDecoder.class, GifDecoder.class, UnitModelLoader.Factory.getInstance())
.append(
Registry.BUCKET_BITMAP,
GifDecoder.class,
Bitmap.class,
new GifFrameResourceDecoder(bitmapPool))
/*添加转换成Drawables相应解码类 Drawables */
.append(Uri.class, Drawable.class, resourceDrawableDecoder)
.append(
Uri.class, Bitmap.class, new ResourceBitmapDecoder(resourceDrawableDecoder, bitmapPool))
/* 添加文件处理类 Files */
.register(new ByteBufferRewinder.Factory())
.append(File.class, ByteBuffer.class, new ByteBufferFileLoader.Factory())
.append(File.class, InputStream.class, new FileLoader.StreamFactory())
.append(File.class, File.class, new FileDecoder())
.append(File.class, ParcelFileDescriptor.class, new FileLoader.FileDescriptorFactory())
// Compilation with Gradle requires the type to be specified for UnitModelLoader here.
.append(File.class, File.class, UnitModelLoader.Factory.getInstance())
/* 添加转换类(将任意复杂的数据模型转化为一个具体的数据类型,然后通过DataFetcher处理得到相应的可用资源) Models */
.register(new InputStreamRewinder.Factory(arrayPool))
//通过资源文件转化成InputStream
.append(int.class, InputStream.class, resourceLoaderStreamFactory)
//通过资源文件转化成ParcelFileDescriptor
.append(
int.class,
ParcelFileDescriptor.class,
resourceLoaderFileDescriptorFactory)
.append(Integer.class, InputStream.class, resourceLoaderStreamFactory)
.append(
Integer.class,
ParcelFileDescriptor.class,
resourceLoaderFileDescriptorFactory)
//通过资源文件转化成Uri
.append(Integer.class, Uri.class, resourceLoaderUriFactory)
.append(
int.class,
AssetFileDescriptor.class,
resourceLoaderAssetFileDescriptorFactory)
.append(
Integer.class,
AssetFileDescriptor.class,
resourceLoaderAssetFileDescriptorFactory)
.append(int.class, Uri.class, resourceLoaderUriFactory)
//通过字符串转化成InputStream
.append(String.class, InputStream.class, new DataUrlLoader.StreamFactory())
//通过Uri转化成InputStream
.append(Uri.class, InputStream.class, new DataUrlLoader.StreamFactory())
//通过String转化成InputStream
.append(String.class, InputStream.class, new StringLoader.StreamFactory())
//通过String转化成ParcelFileDescriptor
.append(String.class, ParcelFileDescriptor.class, new StringLoader.FileDescriptorFactory())
//通过String转化成AssetFileDescriptor
.append(
String.class, AssetFileDescriptor.class, new StringLoader.AssetFileDescriptorFactory())
//通过网络Uri转化成InputStream
.append(Uri.class, InputStream.class, new HttpUriLoader.Factory())
//通过资产目录Uri转化成InputStream
.append(Uri.class, InputStream.class, new AssetUriLoader.StreamFactory(context.getAssets()))
//通过Uri转化成ParcelFileDescriptor
.append(
Uri.class,
ParcelFileDescriptor.class,
new AssetUriLoader.FileDescriptorFactory(context.getAssets()))
//通过image Uri转化成InputStream
.append(Uri.class, InputStream.class, new MediaStoreImageThumbLoader.Factory(context))
//通过video Uri转化成InputStream
.append(Uri.class, InputStream.class, new MediaStoreVideoThumbLoader.Factory(context))
//通过Uri转化成InputStream
.append(
Uri.class,
InputStream.class,
new UriLoader.StreamFactory(contentResolver))
//通过Uri转化成ParcelFileDescriptor
.append(
Uri.class,
ParcelFileDescriptor.class,
new UriLoader.FileDescriptorFactory(contentResolver))
//通过Uri转化成ParcelFileDescriptor
.append(
Uri.class,
AssetFileDescriptor.class,
new UriLoader.AssetFileDescriptorFactory(contentResolver))
//通过http/https Uris转化成InputStream
.append(Uri.class, InputStream.class, new UrlUriLoader.StreamFactory())
//通过java.net.URL转化成InputStream
.append(URL.class, InputStream.class, new UrlLoader.StreamFactory())
//通过java.net.URL转化成InputStream
.append(Uri.class, File.class, new MediaStoreFileLoader.Factory(context))
//通过http/https url转化成InputStream
.append(GlideUrl.class, InputStream.class, new HttpGlideUrlLoader.Factory())
//通过数组转化成ByteBuffer
.append(byte[].class, ByteBuffer.class, new ByteArrayLoader.ByteBufferFactory())
//通过数组转化成InputStream
.append(byte[].class, InputStream.class, new ByteArrayLoader.StreamFactory())
.append(Uri.class, Uri.class, UnitModelLoader.Factory.getInstance())
.append(Drawable.class, Drawable.class, UnitModelLoader.Factory.getInstance())
.append(Drawable.class, Drawable.class, new UnitDrawableDecoder())
/* 注册转码类 bitmap转码成BitmapDrawable Transcoders */
.register(
Bitmap.class,
BitmapDrawable.class,
new BitmapDrawableTranscoder(resources))
//bitmap转码成byte[]
.register(Bitmap.class, byte[].class, bitmapBytesTranscoder)
//Drawable转码成byte[]
.register(
Drawable.class,
byte[].class,
new DrawableBytesTranscoder(
bitmapPool, bitmapBytesTranscoder, gifDrawableBytesTranscoder))
//GifDrawable转码成byte[]
.register(GifDrawable.class, byte[].class, gifDrawableBytesTranscoder);
ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory();
glideContext =
new GlideContext(
context,
arrayPool,
registry,
imageViewTargetFactory,
defaultRequestOptions,
defaultTransitionOptions,
engine,
logLevel);
}
with() 方法 委托给 RequestManagerRetriever 调用 get(Context) 创建 RequestManager
创建 RequestManager 时需要一个 FragmentManager 参数,先创建一个不可见的 Fragment ,通过 FM 加入到当前页面,
fm即可检测页面的生命周期。保证每个 Activity/Fragment 中只包含一个 RequestManagerFragment 与 一个 RequestManager。
RequestManager 主要由两个作用:创建 RequestBuilder 和 通过生命周期管理请求的启动结束等
public RequestManager get(@NonNull Activity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
android.app.FragmentManager fm = activity.getFragmentManager();
//创建一个与fragment生命周期绑定的RequestManager(RequestManager实现了LifecycleListener接口
//并将自己添加到了RequestManagerFragment的ActivityFragmentLifecycle队列中,
//当RequestManagerFragment执行生命周期方法时就会调用LifecycleListener接口实现类,
//从而做出相应的处理暂停请求或移除请求)
return fragmentGet(
activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
}
}
2、load方法
创建一个RequestBuilder 调用 loadGeneric设置 model默认按照Drawable加载
RequestBuilder 用来构建请求,例如设置 RequestOption、缩略图、加载失败占位图等等
3、into方法
Request 主要的实现类有三个:
SingleRequest 这个类负责执行请求并将结果反映到 Target 上
ThumbnailRequestCoordinator 用来协调两个请求,因为有的请求需要同时加载原图和缩略图
ErrorRequestCoordinator 错误
Target 代表一个可被 Glide 加载并且具有生命周期的资源
CustomViewTarget这个是抽象类,负责加载 Bitmap、Drawable 并且放到 View 上
ViewTarget 基本上类似 CustomViewTarget
ImageViewTarget构造器中限定了必须传入 ImageView 或者其子类,图片数据加载完成后会回调其中的 onResourceReady 方法
RequestFutureTarget用来同步加载图片的 Target
AppWidgetTarget用于将下载的 Bitmap 设置到 RemoteView 上
NotificationTarget 用来将 Bitmap 设置到 Notification 中的 RemoteView 上
private > Y into(
@NonNull Y target,
@Nullable RequestListener targetListener,
@NonNull RequestOptions options) {
Util.assertMainThread();
Preconditions.checkNotNull(target);
//判断是否调用了load方法
if (!isModelSet) {
throw new IllegalArgumentException("You must call #load() before calling #into()");
}
//克隆一份请求设置,因为得保证每一个ImageView对应一个options
options = options.autoClone();
//创建请求
Request request = buildRequest(target, targetListener, options);
//获取当前ImageView对应的请求
Request previous = target.getRequest();
//若当前ImageView对应的请求已经设置(即为ImageView设置了tag)
if (request.isEquivalentTo(previous)
&& !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
request.recycle();
// If the request is completed, beginning again will ensure the result is re-delivered,
// triggering RequestListeners and Targets. If the request is failed, beginning again will
// restart the request, giving it another chance to complete. If the request is already
// running, we can let it continue running without interruption.
if (!Preconditions.checkNotNull(previous).isRunning()) {
// Use the previous request rather than the new one to allow for optimizations like skipping
// setting placeholders, tracking and un-tracking Targets, and obtaining View dimensions
// that are done in the individual Request.
previous.begin();
}
return target;
}//先清除当前View的tag
requestManager.clear(target);
//设置当前View tag(即setTag)
target.setRequest(request);
//添加执行request
requestManager.track(target, request);
return target;
}
private Request buildRequestRecursive(
Target target,
@Nullable RequestListener targetListener,
@Nullable RequestCoordinator parentCoordinator,
TransitionOptions, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
RequestOptions requestOptions) {ErrorRequestCoordinator errorRequestCoordinator = null;
//判断是否设置了当前请求错误的错误请求
if (errorBuilder != null) {
errorRequestCoordinator = new ErrorRequestCoordinator(parentCoordinator);
parentCoordinator = errorRequestCoordinator;
}
//构建请求(这里会根据是否设置了获取缩略图请求或缩略比例来创建SingleRequest。这里SingleRequest是从SingleRequestPool中获取的 详见SingleRequest类)
Request mainRequest =
buildThumbnailRequestRecursive(
target,
targetListener,
parentCoordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
requestOptions);
//没有设置错误时的错误请求时则直接返回正常请求
if (errorRequestCoordinator == null) {
return mainRequest;
}int errorOverrideWidth = errorBuilder.requestOptions.getOverrideWidth();
int errorOverrideHeight = errorBuilder.requestOptions.getOverrideHeight();
if (Util.isValidDimensions(overrideWidth, overrideHeight)
&& !errorBuilder.requestOptions.isValidOverride()) {
errorOverrideWidth = requestOptions.getOverrideWidth();
errorOverrideHeight = requestOptions.getOverrideHeight();
}Request errorRequest = errorBuilder.buildRequestRecursive(
target,
targetListener,
errorRequestCoordinator,
errorBuilder.transitionOptions,
errorBuilder.requestOptions.getPriority(),
errorOverrideWidth,
errorOverrideHeight,
errorBuilder.requestOptions);
//设置错误时的错误请求时则添加errorRequest
errorRequestCoordinator.setRequests(mainRequest, errorRequest);
return errorRequestCoordinator;
}
public void begin() {
assertNotCallingCallbacks();
stateVerifier.throwIfRecycled();
startTime = LogTime.getLogTime();
//判断加载的内容模型是否为空
if (model == null) {
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
width = overrideWidth;
height = overrideHeight;
}
// Only log at more verbose log levels if the user has set a fallback drawable, because
// fallback Drawables indicate the user expects null models occasionally.
int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG;
onLoadFailed(new GlideException("Received null model"), logLevel);
return;
}//当前请求正在执行中...
if (status == Status.RUNNING) {
throw new IllegalArgumentException("Cannot restart a running request");
}//当前请求已经执行完成
if (status == Status.COMPLETE) {
onResourceReady(resource, DataSource.MEMORY_CACHE);
return;
}
//设置请求图片的宽高
status = Status.WAITING_FOR_SIZE;
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
//开始请求
onSizeReady(overrideWidth, overrideHeight);
} else {
//获取当前View的宽高之后 再调用onSizeReady方法
target.getSize(this);
}//正在请求时 设置PlaceholderDrawable图片
if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
&& canNotifyStatusChanged()) {
target.onLoadStarted(getPlaceholderDrawable());
}
if (IS_VERBOSE_LOGGABLE) {
logV("finished run method in " + LogTime.getElapsedMillis(startTime));
}
}
EngineJob主要用来执行 DecodeJob 以及管理加载完成的回调,各种监听器
DecodeJob负责从缓存或数据源中加载原始数据并通过解码器转换为相应的资源类型(Resource)。DecodeJob 实现了 Runnable 接口,由 EngineJob 将其运行在指定线程池中。
public LoadStatus load(
GlideContext glideContext,
Object model,
Key signature,
int width,
int height,
Class> resourceClass,
Class transcodeClass,
Priority priority,
DiskCacheStrategy diskCacheStrategy,
Map, Transformation>> transformations,
boolean isTransformationRequired,
boolean isScaleOnlyOrNoTransform,
Options options,
boolean isMemoryCacheable,
boolean useUnlimitedSourceExecutorPool,
boolean useAnimationPool,
boolean onlyRetrieveFromCache,
ResourceCallback cb) {
Util.assertMainThread();
long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;
//更新相应属性创建EngineKey
EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,
resourceClass, transcodeClass, options);
//尝试从活跃的资源内存缓存中中获取
EngineResource> active = loadFromActiveResources(key, isMemoryCacheable);
if (active != null) {
cb.onResourceReady(active, DataSource.MEMORY_CACHE);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Loaded resource from active resources", startTime, key);
}
return null;
}
//尝试从内存缓存中获取
EngineResource> cached = loadFromCache(key, isMemoryCacheable);
if (cached != null) {
cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Loaded resource from cache", startTime, key);
}
return null;
}
//判断当前请求是在在队列中
EngineJob> current = jobs.get(key, onlyRetrieveFromCache);
if (current != null) {
current.addCallback(cb);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Added to existing load", startTime, key);
}
return new LoadStatus(cb, current);
}
//创建请求job
EngineJob engineJob =
engineJobFactory.build(
key,
isMemoryCacheable,
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache);
//创建解码job
DecodeJob decodeJob =
decodeJobFactory.build(
glideContext,
model,
key,
signature,
width,
height,
resourceClass,
transcodeClass,
priority,
diskCacheStrategy,
transformations,
isTransformationRequired,
isScaleOnlyOrNoTransform,
onlyRetrieveFromCache,
options,
engineJob);
//保存当前请求job
jobs.put(key, engineJob);
engineJob.addCallback(cb);
//开始请求
engineJob.start(decodeJob);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Started new load", startTime, key);
}
return new LoadStatus(cb, engineJob);
}
DataFetcher 内部实现就是通过 HttpUrlConnect 发起网络请求,或者打开一个文件,或者使用 AssetManager 打开一个资源等等
public void start(DecodeJob decodeJob) {
this.decodeJob = decodeJob;
GlideExecutor executor = decodeJob.willDecodeFromCache()
? diskCacheExecutor
: getActiveSourceExecutor();
executor.execute(decodeJob);
}//DecodeJob 的 run方法内
private void runWrapped() {
switch (runReason) {
case INITIALIZE:
stage = getNextStage(Stage.INITIALIZE);
//根据当前流程步骤获取相应获取数据类(刚开始肯定为INITIALIZE初始化状态)
currentGenerator = getNextGenerator();
runGenerators();
break;
case SWITCH_TO_SOURCE_SERVICE:
runGenerators();
break;
case DECODE_DATA:
decodeFromRetrievedData();
break;
default:
throw new IllegalStateException("Unrecognized run reason: " + runReason);
}
}private DataFetcherGenerator getNextGenerator() {
switch (stage) {
//从内存缓存中获取
case RESOURCE_CACHE:
return new ResourceCacheGenerator(decodeHelper, this);
//从文件缓存中获取
case DATA_CACHE:
return new DataCacheGenerator(decodeHelper, this);
case SOURCE:
//从相应的资源中获取
return new SourceGenerator(decodeHelper, this);
case FINISHED:
return null;
default:
throw new IllegalStateException("Unrecognized stage: " + stage);
}
}private void runGenerators() {
currentThread = Thread.currentThread();
startFetchTime = LogTime.getLogTime();
boolean isStarted = false;
//依次从内存、文件及相应资源中获取。
while (!isCancelled && currentGenerator != null
&& !(isStarted = currentGenerator.startNext())) {
stage = getNextStage(stage);
currentGenerator = getNextGenerator();
if (stage == Stage.SOURCE) {
reschedule();
return;
}
}
// We've run out of stages and generators, give up.
if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {
notifyFailed();
}// Otherwise a generator started a new load and we expect to be called back in
// onDataFetcherReady.
}
@Override
public boolean startNext() {
//判断当前请求是否成功,成了调用DataCacheGenerator的next方法,从而生成相应的图片
if (dataToCache != null) {
Object data = https://www.it610.com/article/dataToCache;
dataToCache = null;
cacheData(data);
}if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
return true;
}
sourceCacheGenerator = null;
loadData = null;
boolean started = false;
//依次从注册了处理该资源的实例
while (!started && hasNextModelLoader()) {
loadData = helper.getLoadData().get(loadDataListIndex++);
if (loadData != null
&& (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
|| helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
started = true;
//开始加载资源
loadData.fetcher.loadData(helper.getPriority(), this);
}
}
return started;
}
//从registry中匹配相应的Modeloader来加载数据。这里是从HttpUrlFetcher。
public void loadData(@NonNull Priority priority,
@NonNull DataCallback super InputStream> callback) {
long startTime = LogTime.getLogTime();
try {
//连接网络获取图片流
InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
//成功回调
callback.onDataReady(result);
} catch (IOException e) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Failed to load data for url", e);
}
callback.onLoadFailed(e);
} finally {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Finished http url fetcher fetch in " + LogTime.getElapsedMillis(startTime));
}
}
}请求成功之后回调了DataCallback方法。最终会回调到DecodeJob的onDataFetcherReady方法,之后在进行解码操作private void decodeFromRetrievedData() {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Retrieved data", startFetchTime,
"data: " + currentData
+ ", cache key: " + currentSourceKey
+ ", fetcher: " + currentFetcher);
}
Resource resource = null;
try {
//进行解码(从registery中匹配相应的解码实例类Downsampler进行解码)
resource = decodeFromData(currentFetcher, currentData, currentDataSource);
} catch (GlideException e) {
e.setLoggingDetails(currentAttemptingKey, currentDataSource);
throwables.add(e);
}
if (resource != null) {
//解码成功
notifyEncodeAndRelease(resource, currentDataSource);
} else {
//解码失败进行下一步操作
runGenerators();
}
}public void onResourceReady(Resource resource, DataSource dataSource) {
this.resource = resource;
this.dataSource = dataSource;
MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();
}通过handler切换至主线程
public boolean handleMessage(Message message) {
EngineJob> job = (EngineJob>) message.obj;
switch (message.what) {
case MSG_COMPLETE:
job.handleResultOnMainThread();
break;
case MSG_EXCEPTION:
job.handleExceptionOnMainThread();
break;
case MSG_CANCELLED:
job.handleCancelledOnMainThread();
break;
default:
throw new IllegalStateException("Unrecognized message: " + message.what);
}
return true;
}将Bitmap设置给ViewImage。至此就完成了一张图片的加载。
void handleResultOnMainThread() {
stateVerifier.throwIfRecycled();
if (isCancelled) {
resource.recycle();
release(false /*isRemovedFromQueue*/);
return;
} else if (cbs.isEmpty()) {
throw new IllegalStateException("Received a resource without any callbacks to notify");
} else if (hasResource) {
throw new IllegalStateException("Already have resource");
}
engineResource = engineResourceFactory.build(resource, isCacheable);
hasResource = true;
// Hold on to resource for duration of request so we don't recycle it in the middle of
// notifying if it synchronously released by one of the callbacks.
engineResource.acquire();
listener.onEngineJobComplete(this, key, engineResource);
//noinspection ForLoopReplaceableByForEach to improve perf
for (int i = 0, size = cbs.size();
i < size;
i++) {
ResourceCallback cb = cbs.get(i);
if (!isInIgnoredCallbacks(cb)) {
engineResource.acquire();
cb.onResourceReady(engineResource, dataSource);
}
}
// Our request is complete, so we can release the resource.
engineResource.release();
release(false /*isRemovedFromQueue*/);
}
private void onResourceReady(Resource resource, R result, DataSource dataSource) {
// We must call isFirstReadyResource before setting status.
boolean isFirstResource = isFirstReadyResource();
status = Status.COMPLETE;
this.resource = resource;
if (glideContext.getLogLevel() <= Log.DEBUG) {
Log.d(GLIDE_TAG, "Finished loading " + result.getClass().getSimpleName() + " from "
+ dataSource + " for " + model + " with size [" + width + "x" + height + "] in "
+ LogTime.getElapsedMillis(startTime) + " ms");
}isCallingCallbacks = true;
try {
boolean anyListenerHandledUpdatingTarget = false;
//是否设置了加载成功的监听并且判断返回值是否为true
if (requestListeners != null) {
for (RequestListener listener : requestListeners) {
anyListenerHandledUpdatingTarget |=
listener.onResourceReady(result, model, target, dataSource, isFirstResource);
}
}
anyListenerHandledUpdatingTarget |=
targetListener != null
&& targetListener.onResourceReady(result, model, target, dataSource, isFirstResource);
//加载动画
if (!anyListenerHandledUpdatingTarget) {
Transition super R> animation =
animationFactory.build(dataSource, isFirstResource);
target.onResourceReady(result, animation);
}
} finally {
isCallingCallbacks = false;
}notifyLoadSuccess();
}
4、Glide加载Gif图片的原理就是将gif根据每一帧解析成很多张图片,然后在依次设置给ImageView
5、三级缓存
第一级缓存ActiveResources,表示当前正在活动中的资源
ActiveResources 中通过一个 Map 来存储数据,数据保存在一个虚引用(WeakReference)中。
ReferenceQueue 的具体作用大概就是用来跟踪弱引用(或者软引用、虚引用)是否被 gc 的。
MessageQueue.IdleHandler 对象,Handler 会在线程空闲时调用这个方法
MemorySizeCalculator用来计算 BitmapPool 、ArrayPool 以及 MemoryCache 大小
BitmapPoolBitmap 是用来复用 Bitmap 从而避免重复创建 Bitmap 而带来的内存浪费
LruBitmapPool主要任务都交给了 LruPoolStrategy,这里只是做一些缓存大小管理、封装、日志记录等等操作
LruPoolStrategy 有两个实现类:SizeConfigStrategy 以及 AttributeStrategy
SizeConfigStrategy 顾名思义,是通过 Bitmap 的 size 与 Config 来当做 key 缓存 Bitmap,Key 也会通过 KeyPool 来缓存在一个队列(Queue)中。
与 AttributeStrategy 相同的是,其中都使用 Glide 内部自定义的数据结构:GroupedLinkedMap 来存储 Bitmap。
BitmapPool 大小通过 MemorySizeCalculator 设置;
使用 LRU 算法维护 BitmapPool ;
Glide 会根据 Bitmap 的大小与 Config 生成一个 Key;
Key 也有自己对应的对象池,使用 Queue 实现;
数据最终存储在 GroupedLinkedMap 中;
GroupedLinkedMap 使用哈希表、循环链表、List 来存储数据。
第二级缓存 MemoryCache
内存缓存同样使用 LRU 算法,实现类为 LruResourceCache
第三级缓存 磁盘缓存
磁盘缓存实现类由 InternalCacheDiskCacheFactory 创建,最终会通过缓存路径及缓存文件夹最大值创建一个 DiskLruCacheWrapper 对象
缓存路径默认为 Context#getCacheDir() 下面的 image_manager_disk_cache 文件夹,默认缓存大小为 250MB。
DiskLruCache
Glide 是使用一个日志清单文件来保存这种顺序,DiskLruCache 在 APP 第一次安装时会在缓存文件夹下创建一个 journal 日志文件来记录图片的添加、删除、读取等等操作,后面每次打开 APP 都会读取这个文件,把其中记录下来的缓存文件名读取到 LinkedHashMap 中,后面每次对图片的操作不仅是操作这个 LinkedHashMap 还要记录在 journal 文件中.
推荐阅读
- Android事件传递源码分析
- Quartz|Quartz 源码解析(四) —— QuartzScheduler和Listener事件监听
- Java内存泄漏分析系列之二(jstack生成的Thread|Java内存泄漏分析系列之二:jstack生成的Thread Dump日志结构解析)
- [源码解析]|[源码解析] NVIDIA HugeCTR,GPU版本参数服务器---(3)
- ffmpeg源码分析01(结构体)
- Android系统启动之init.rc文件解析过程
- Java程序员阅读源码的小技巧,原来大牛都是这样读的,赶紧看看!
- 小程序有哪些低成本获客手段——案例解析
- Vue源码分析—响应式原理(二)
- SwiftUI|SwiftUI iOS 瀑布流组件之仿CollectionView不规则图文混合(教程含源码)