Glide作为一个图片加载框架深受开发者喜欢,包体积小,加载速度快,以及加载圆角等。作为一名开发者我们有必要去了解Glide图片加载机制,它是如何把图片加载出来的?以及在图片加载过程中它都做了什么?
@NonNull
public static RequestManager with(@NonNull FragmentActivity activity) {
// 1.调用 getRetriever 方法获取到RequestManagerRetriever
// 2.RequestManagerRetriever.get()获取到RequestManager 图片请求管理者
return getRetriever(activity).get(activity);
}
@NonNull
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
// 1.调用Glide.get()方法获取Glied对象
// 2.调用getRequestManagerRetriever()获取到 RequestManagerRetriever
return Glide.get(context).getRequestManagerRetriever();
}
Glide 调用 with() 方法,可以看出主要做了两件事:
1.通过 getRetriever() 获取RequestManagerRetriever对象
2.通过 RequestManagerRetriever对象 拿到requestManage 图片请求管理者
public class Glide implements ComponentCallbacks2 {
/**
* 单利模式获取Glide对象
*/
@NonNull
public static Glide get(@NonNull Context context) {
if (glide == null) {
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context);
}
}
}
return glide;
}
private static void checkAndInitializeGlide(@NonNull Context context) {
if (isInitializing) {
throw new IllegalStateException("You cannot call Glide.get() in registerComponents(),"
+ " use the provided Glide instance instead");
}
//防止多次调用Glide.get()方法
isInitializing = true;
initializeGlide(context);
isInitializing = false;
}
private static void initializeGlide(@NonNull Context context) {
initializeGlide(context, new GlideBuilder());
}
private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
Context applicationContext = context.getApplicationContext();
// 1.获取 @GlideModule 注解驱动生成的 GeneratedAppGlideModuleImpl 和 GeneratedAppGlideModuleFactory 类
GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
// 2.从annotationGeneratedModule中获取RequestManager构造工厂对象
RequestManagerRetriever.RequestManagerFactory factory =
annotationGeneratedModule != null
? annotationGeneratedModule.getRequestManagerFactory() : null;
// 3.添加到 GlideBuilder 中
builder.setRequestManagerFactory(factory);
// 4.构造 glide 对象
Glide glide = builder.build(applicationContext);
// 5. 向 Application 中注册一个组件的回调, 用于检测系统 Config 改变和内存占用量低的信号
applicationContext.registerComponentCallbacks(glide);
// 6.保存为静态常量
Glide.glide = glide;
}
在initializeGlide()方法中获取 @GlideModule 注解生成类,然后获取到获取RequestManager构造工厂对象,添加到 GlideBuilder 中,构造出glide对象
具体看看glied对象创建过程:
public final class GlideBuilder {
// 1.线程池
private GlideExecutor sourceExecutor;
private GlideExecutor diskCacheExecutor;
private GlideExecutor animationExecutor;
// 2.缓存大小设置
private MemorySizeCalculator memorySizeCalculator;
// 3.图片享元复用池
private BitmapPool bitmapPool;
private ArrayPool arrayPool;
// 4.缓存策略
private MemoryCache memoryCache;
// 5.资源管理与程池的引擎
private Engine engine;
// 6.设置默认的 RequestOptions
private RequestOptions defaultRequestOptions = new RequestOptions();
// 7. 磁盘缓存和请求构建工厂
private DiskCache.Factory diskCacheFactory;
private RequestManagerFactory requestManagerFactory;
......
Glide build(@NonNull Context context) {
// 1.1 网络操作使用线程池
if (sourceExecutor == null) {
sourceExecutor = GlideExecutor.newSourceExecutor();
}
// 1.2磁盘缓存线程池
if (diskCacheExecutor == null) {
diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
}
// 1.3 执行动画线程池
if (animationExecutor == null) {
animationExecutor = GlideExecutor.newAnimationExecutor();
}
// 2.1 基于屏幕分辨率,宽高等条件设置缓存大小
if (memorySizeCalculator == null) {
memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
}
// 3.1 bitmap 复用池
if (bitmapPool == null) {
int size = memorySizeCalculator.getBitmapPoolSize();
}
// 3.2 数组复用池
if (arrayPool == null) {
arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
}
// 4.1内存缓存策略
if (memoryCache == null) {
memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
}
// 4.2 磁盘缓存工厂
if (diskCacheFactory == null) {
diskCacheFactory = new InternalCacheDiskCacheFactory(context);
}
// 5.资源管理与程池的引擎
if (engine == null) {
engine =
new Engine(
memoryCache,
diskCacheFactory,
diskCacheExecutor,
sourceExecutor,
GlideExecutor.newUnlimitedSourceExecutor(),
GlideExecutor.newAnimationExecutor(),
isActiveResourceRetentionAllowed);
}
// 6.创建了一个 RequestManagerRetriever对象
RequestManagerRetriever requestManagerRetriever =
new RequestManagerRetriever(requestManagerFactory);
// 7.创建了Glide对象
return new Glide(
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptions.lock(),
defaultTransitionOptions,
defaultRequestListeners,
isLoggingRequestOriginsEnabled);
}
可以看到,在创建glide对象时,会创建 RequestManagerRetriever对象,返回回去,再去调用RequestManager的get()方法,这个方法也挺重要,一起分析下
public RequestManager get(@NonNull FragmentActivity activity) {
//区分在哪个线程中执行的
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
//拿到fragment的管理者
FragmentManager fm = activity.getSupportFragmentManager();
return supportFragmentGet(
activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
}
}
private RequestManager supportFragmentGet(
@NonNull Context context,
@NonNull FragmentManager fm,
@Nullable Fragment parentHint,
boolean isParentVisible) {
// 1.从activity中获取requestManager,用于监管activity的生命周期
SupportRequestManagerFragment current =
getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
// 2.获取当前页面中的请求管理器requestManager
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
Glide glide = Glide.get(context);
// 3.不存在就创建一个,保存在 SupportRequestManagerFragment 中
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);
}
return requestManager;
}
private SupportRequestManagerFragment getSupportRequestManagerFragment(
@NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
// 2.1通过Tag拿到 RequestManagerFragment,第一次应该是空
SupportRequestManagerFragment current =
(SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
// 2.2 如果为空,就从HasMap中取
current = pendingSupportRequestManagerFragments.get(fm);
if (current == null) {
// 2.3还为空 就创建一个
current = new SupportRequestManagerFragment();
current.setParentFragmentHint(parentHint);
if (isParentVisible) {
current.getGlideLifecycle().onStart();
}
// 2.4添加到缓存中
pendingSupportRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
//2.5添加成功,移除缓存
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
//返回requestManage
return current;
}
// 2.2.1 是一个HasMap
final Map<FragmentManager, SupportRequestManagerFragment> pendingSupportRequestManagerFragments =
new HashMap<>();
可以看出Glide.with()方法主要做了两件事,1.创建glide对象 2.获取到当前界面的生命周期。获取到glide对象很好理解,为何要获取当前界面的生命周期呢?我们都知道图片加载的速度慢于界面加载的速度,通过界面的生命周期,我们就能控制glide是否要继续加载未加载完的图片等,稍后还要继续分析。
RequestManage.java
public RequestBuilder<Drawable> load(@Nullable String string) {
return asDrawable().load(string);
}
public RequestBuilder<Drawable> asDrawable() {
return as(Drawable.class);
}
//参数是 Drawable类型
public <ResourceType> RequestBuilder<ResourceType> as(
@NonNull Class<ResourceType> resourceClass) {
//创建了一个RequestBuilder
//this指代RequestManage
return new RequestBuilder<>(glide, this, resourceClass, context);
}
RequestBuilder.java
protected RequestBuilder(
@NonNull Glide glide,
RequestManager requestManager,
Class<TranscodeType> transcodeClass,
Context context) {
this.glide = glide;
this.requestManager = requestManager;
this.transcodeClass = transcodeClass;
this.context = context;
this.transitionOptions = requestManager.getDefaultTransitionOptions(transcodeClass);
this.glideContext = glide.getGlideContext();
//为requestBuild 添加监听
initRequestListeners(requestManager.getDefaultRequestListeners());
//设置默认RequestOption
apply(requestManager.getDefaultRequestOptions());
}
public T apply(@NonNull BaseRequestOptions<?> o) {
if (isAutoCloneEnabled) {
return clone().apply(o);
}
BaseRequestOptions<?> other = o;
if (isSet(other.fields, SIZE_MULTIPLIER)) {
sizeMultiplier = other.sizeMultiplier;
}
if (isSet(other.fields, USE_UNLIMITED_SOURCE_GENERATORS_POOL)) {
useUnlimitedSourceGeneratorsPool = other.useUnlimitedSourceGeneratorsPool;
}
if (isSet(other.fields, USE_ANIMATION_POOL)) {
useAnimationPool = other.useAnimationPool;
}
if (isSet(other.fields, DISK_CACHE_STRATEGY)) {
diskCacheStrategy = other.diskCacheStrategy;
}
if (isSet(other.fields, PRIORITY)) {
priority = other.priority;
}
if (isSet(other.fields, ERROR_PLACEHOLDER)) {
errorPlaceholder = other.errorPlaceholder;
errorId = 0;
fields &= ~ERROR_ID;
}
if (isSet(other.fields, ERROR_ID)) {
errorId = other.errorId;
errorPlaceholder = null;
fields &= ~ERROR_PLACEHOLDER;
}
if (isSet(other.fields, PLACEHOLDER)) {
placeholderDrawable = other.placeholderDrawable;
placeholderId = 0;
fields &= ~PLACEHOLDER_ID;
}
if (isSet(other.fields, PLACEHOLDER_ID)) {
placeholderId = other.placeholderId;
placeholderDrawable = null;
fields &= ~PLACEHOLDER;
}
if (isSet(other.fields, IS_CACHEABLE)) {
isCacheable = other.isCacheable;
}
if (isSet(other.fields, OVERRIDE)) {
overrideWidth = other.overrideWidth;
overrideHeight = other.overrideHeight;
}
if (isSet(other.fields, SIGNATURE)) {
signature = other.signature;
}
if (isSet(other.fields, RESOURCE_CLASS)) {
resourceClass = other.resourceClass;
}
if (isSet(other.fields, FALLBACK)) {
fallbackDrawable = other.fallbackDrawable;
fallbackId = 0;
fields &= ~FALLBACK_ID;
}
if (isSet(other.fields, FALLBACK_ID)) {
fallbackId = other.fallbackId;
fallbackDrawable = null;
fields &= ~FALLBACK;
}
if (isSet(other.fields, THEME)) {
theme = other.theme;
}
if (isSet(other.fields, TRANSFORMATION_ALLOWED)) {
isTransformationAllowed = other.isTransformationAllowed;
}
if (isSet(other.fields, TRANSFORMATION_REQUIRED)) {
isTransformationRequired = other.isTransformationRequired;
}
if (isSet(other.fields, TRANSFORMATION)) {
transformations.putAll(other.transformations);
isScaleOnlyOrNoTransform = other.isScaleOnlyOrNoTransform;
}
if (isSet(other.fields, ONLY_RETRIEVE_FROM_CACHE)) {
onlyRetrieveFromCache = other.onlyRetrieveFromCache;
}
// Applying options with dontTransform() is expected to clear our transformations.
if (!isTransformationAllowed) {
transformations.clear();
fields &= ~TRANSFORMATION;
isTransformationRequired = false;
fields &= ~TRANSFORMATION_REQUIRED;
isScaleOnlyOrNoTransform = true;
}
fields |= other.fields;
options.putAll(other.options);
return selfOrThrowIfLocked();
}
public RequestBuilder<TranscodeType> load(@Nullable String string) {
return loadGeneric(string);
}
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
this.model = model;
isModelSet = true;
return this;
}
load主要做了那些事情呢?1.构建了RequestBuilder2.initRequestListeners添加监听3.设置默认的RequestOption,4.设置加载图片的地址
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
//requestBuild继承了BaseRequestOptions
BaseRequestOptions<?> requestOptions = this;
if (!requestOptions.isTransformationSet()
&& requestOptions.isTransformationAllowed()
//缩放的类型不是null
&& view.getScaleType() != null) {
// View's缩放类型
switch (view.getScaleType()) {
case CENTER_CROP:
requestOptions = requestOptions.clone().optionalCenterCrop();
break;
case CENTER_INSIDE:
requestOptions = requestOptions.clone().optionalCenterInside();
break;
case FIT_CENTER:
case FIT_START:
case FIT_END:
requestOptions = requestOptions.clone().optionalFitCenter();
break;
case FIT_XY:
requestOptions = requestOptions.clone().optionalCenterInside();
break;
case CENTER:
case MATRIX:
default:
// Do nothing.
}
}
return into(
//创建一个viewTarget
glideContext.buildImageViewTarget(view, transcodeClass),
null,
requestOptions,
Executors.mainThreadExecutor());
}
public <X> ViewTarget<ImageView, X> buildImageViewTarget(
@NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
//通过target工厂类创建target,transcodeClass 是Drawable.class
return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
}
public <Z> ViewTarget<ImageView, Z> buildTarget(@NonNull ImageView view,
@NonNull Class<Z> clazz) {
// 当前传入的clazz 是 Drawable.class
if (Bitmap.class.equals(clazz)) {
return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view);
} else if (Drawable.class.isAssignableFrom(clazz)) {
return (ViewTarget<ImageView, Z>) new DrawableImageViewTarget(view);
} else {
throw new IllegalArgumentException(
"Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
}
}
最终返回一个DrawableImageViewTarget
//接下来继续走 into() 方法
private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> options,
Executor callbackExecutor) {
Preconditions.checkNotNull(target);
// isModelSet 在load()时设置了isModelSet=true;
if (!isModelSet) {
throw new IllegalArgumentException("You must call #load() before calling #into()");
}
//根据当前传入的 target,option 创建一个请求
Request request = buildRequest(target, targetListener, options, callbackExecutor);
//从当前target中获取request
Request previous = target.getRequest();
// isEquivalentTo 是用来判断新创建的request是否是已经创建了的previous,意思是此target// 是否已经创建过了request,避免重复创建;isSkipMemoryCacheWithCompletePreviousReque// st方法是判断此request是否正在请求中或是请求已经完成
if (request.isEquivalentTo(previous)
&& !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
// 满足以上两个条件,那么刚创建的request可以回收了
request.recycle();
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;
}
//清空target的任何请求
requestManager.clear(target);
//给target 设置请求
target.setRequest(request);
//requestManager 分发任务
requestManager.track(target, request);
return target;
}
synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
// 将target放入set集合中
targetTracker.track(target);
//准备请求
requestTracker.runRequest(request);
}
private final Set<Request> requests =
Collections.newSetFromMap(new WeakHashMap<Request, Boolean>());
public void runRequest(@NonNull Request request) {
//将请求加入set集合中
requests.add(request);
//判断界面是否可见
if (!isPaused) {
//开始请求
request.begin();
} else {
//不可见就取消请求
request.clear();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Paused, delaying request");
}
pendingRequests.add(request);
}
}
public final class SingleRequest<R> implements Request,
SizeReadyCallback,
ResourceCallback,
FactoryPools.Poolable {
@Override
public synchronized void begin() {
//modle是传入的url
if (model == null) {
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
width = overrideWidth;
height = overrideHeight;
}
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 {
target.getSize(this);
}
}
@Override
public synchronized void onSizeReady(int width, int height) {
// 调用了 Engine.load 方法构建任务
loadStatus = engine.load(glideContext,model.....);
}
}
可以看到 onSizeReady 去构建可执行任务, 接下来我们就分析这一过程。
public class Engine implements EngineJobListener,
MemoryCache.ResourceRemovedListener,
EngineResource.ResourceListener {
public synchronized <R> LoadStatus load(....) {
//1.通过传入的参数构建一个EngineKey
EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,
resourceClass, transcodeClass, options);
// 2. 从缓存中查找 key 对应的资源
// 2.1 尝试从 ActiveResources 缓存中查找这个 key 的缓存(内存缓存)
EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
if (active != null) {
// 若缓存存在, 则直接回调 onResourceReady 处理后续操作
cb.onResourceReady(active, DataSource.MEMORY_CACHE);
return null;
}
// 2.2 尝试从 LruResourceCache 中找寻这个资源
EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
if (cached != null) {
cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
return null;
}
// 3. 尝试从 请求任务 中找寻这个资源
EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
if (current != null) {
// 3.1 走到这里说明这个任务已经正在执行了, 无需再次构建执行
current.addCallback(cb, callbackExecutor);
//返回一个LoadStatus状态
return new LoadStatus(cb, current);
}
// 3.2 走到这里, 说明是一个新的任务
// 3.2.1 则构建一个新的引擎任务
EngineJob<R> engineJob = engineJobFactory.build(...);
// 3.2.2 构建解码任务
DecodeJob<R> decodeJob = decodeJobFactory.build(...);
// 3.2.3 添加到任务缓存,防止多次构建
jobs.put(key, engineJob);
...
// 3.2.4 执行任务
engineJob.start(decodeJob);
//返回一个LoadStatus状态
return new LoadStatus(cb, engineJob);
}
}
可以看出Engine.load()方法做了几件重要的事
好的, 可以看到内存缓存的处理是在 Engine 中进行的, 若两个内存缓存都没有命中, 则会构建任务并执行, 接下来我们看看任务的执行过程
public synchronized void start(DecodeJob<R> decodeJob) {
this.decodeJob = decodeJob;
//获取执行的线程池
GlideExecutor executor = decodeJob.willDecodeFromCache()
? diskCacheExecutor
: getActiveSourceExecutor();
// 执行任务
executor.execute(decodeJob);
}
class DecodeJob<R> implements DataFetcherGenerator.FetcherReadyCallback,
Runnable,
Comparable<DecodeJob<?>>,
Poolable {
@Override
public void run() {
try {
...
// 调用了 runWrapped
runWrapped();
...
}
}
private void runWrapped() {
switch (runReason) {
case INITIALIZE:
// 1. 获取任务的场景
stage = getNextStage(Stage.INITIALIZE);
// 2. 获取这个场景的执行者
currentGenerator = getNextGenerator();
// 3. 执行者执行任务
runGenerators();
break;
case SWITCH_TO_SOURCE_SERVICE:
runGenerators();
break;
case DECODE_DATA:
decodeFromRetrievedData();
break;
default:
throw new IllegalStateException("Unrecognized run reason: " + runReason);
}
}
private Stage getNextStage(Stage current) {
switch (current) {
case INITIALIZE:
// 1.1 若我们配置的缓存策略允许从 资源缓存 中读数据, 则返回 Stage.RESOURCE_CACHE
return diskCacheStrategy.decodeCachedResource()
? Stage.RESOURCE_CACHE : getNextStage(Stage.RESOURCE_CACHE);
case RESOURCE_CACHE:
// 1.2 若我们配置的缓存策略允许从 源数据缓存中读数据, 则返回 Stage.DATA_CACHE
return diskCacheStrategy.decodeCachedData()
? Stage.DATA_CACHE : getNextStage(Stage.DATA_CACHE);
case DATA_CACHE:
// 1.3 若只能允许从缓存中获取数据, 则直接 FINISH, 否则返回 Stage.SOURCE, 意为加载一个新的资源
return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
case SOURCE:
case FINISHED:
return Stage.FINISHED;
default:
throw new IllegalArgumentException("Unrecognized stage: " + current);
}
}
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() {
// 调用 DataFetcherGenerator.startNext() 执行了请求操作
while (!isCancelled && currentGenerator != null
&& !(isStarted = currentGenerator.startNext())) {
stage = getNextStage(stage);
currentGenerator = getNextGenerator();
if (stage == Stage.SOURCE) {
reschedule();
return;
}
}
}
}
DecodeJob 任务执行时, 它根据不同的场景, 获取不同的场景执行器, 然后调用了它们的 startNext 方法加载请求任务的数据, 其映射表为
场景 | 场景描述 | 场景执行器 |
---|---|---|
Stage.RESOURCE_CACHE | 从磁盘中缓存的资源中获取数据 | ResourceCacheGenerator |
Stage.DATA_CACHE | 从磁盘中缓存的源数据中获取数据 | DataCacheGenerator |
Stage.SOURCE | 重新请求数据 | SourceGenerator |
我们知道在 Engine 中, 尝试从内存缓存中获取资源, 而 DecodeJob 则是尝试从磁盘缓存中获取资源, 我们这里主要查看 SourceGenerator.startNext 是如何加载请求任务的数据的
class SourceGenerator implements DataFetcherGenerator,
DataFetcher.DataCallback<Object>,
DataFetcherGenerator.FetcherReadyCallback {
@Override
public boolean startNext() {
...
loadData = null;
boolean started = false;
while (!started && hasNextModelLoader()) {
// 1. 从 DecodeHelper 的数据加载集合中, 获取一个数据加载器
loadData = helper.getLoadData().get(loadDataListIndex++);
if (loadData != null
&& (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
|| helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
started = true;
// 2. 使用加载器中 fetcher 执行数据加载
loadData.fetcher.loadData(helper.getPriority(), this);
}
}
return started;
}
}
可以看出SourceGenerator主要有两步
final class DecodeHelper<Transcode> {
List<LoadData<?>> getLoadData() {
if (!isLoadDataSet) {
isLoadDataSet = true;
loadData.clear();
// 1. 从 Glide 注册的 register 中获取请求 model 加载器
List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model);
// 遍历每一个 modelLoaders
for (int i = 0, size = modelLoaders.size(); i < size; i++) {
ModelLoader<Object, ?> modelLoader = modelLoaders.get(i);
//通过传入的参数获取 loadData
LoadData<?> current =
modelLoader.buildLoadData(model, width, height, options);
if (current != null) {
loadData.add(current);
}
}
}
return loadData;
}
}
它会找到一个 ModelLoader 的实现类, 通过这个实现类的 handles 方法, 判断是否可以加载这个 model
这里我们的 model 以网络的 URL 资源举例, 它的实现类为 HttpGlideUrlLoader 我们看看它如何构建一个 LoadData 对象的
public class HttpGlideUrlLoader implements ModelLoader<GlideUrl, InputStream> {
@Override
public LoadData<InputStream> buildLoadData(@NonNull GlideUrl model, int width, int height, @NonNull Options options) {
GlideUrl url = model;
...
int timeout = options.get(TIMEOUT);
// 创建了一个 LoadData 对象, 并且实例化了一个 HttpUrlFetcher 给它
return new LoadData<>(url, new HttpUrlFetcher(url, timeout));
}
}
好的, 可以看到对于 URL 的加载, 其 fetcher 为一个 HttpUrlFetcher 的实例, 接下来我们看看数据加载的流程
public class HttpUrlFetcher implements DataFetcher<InputStream> {
@Override
public void loadData(@NonNull Priority priority,
@NonNull DataCallback<? super InputStream> callback) {
long startTime = LogTime.getLogTime();
try {
//发起请求,获得InputStream
InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
//回掉结果
callback.onDataReady(result);
} catch (IOException e) {
//出现异常
callback.onLoadFailed(e);
}
}
}
接下来看看urlConnection的请求
public class HttpUrlFetcher implements DataFetcher<InputStream> {
private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl,
Map<String, String> headers) throws IOException {
// 1.构建一个 urlConnection
urlConnection = connectionFactory.build(url);
// 2.设置head头
for (Map.Entry<String, String> headerEntry : headers.entrySet()) {
urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());
}
...
// 3.是否进行重定向
urlConnection.setInstanceFollowRedirects(false);
// 4.发起请求
urlConnection.connect();
// 拿到inputstrean
stream = urlConnection.getInputStream();
if (isCancelled) {
return null;
}
final int statusCode = urlConnection.getResponseCode();
if (isHttpOk(statusCode)) {
// statusCode==200
return getStreamForSuccessfulRequest(urlConnection);
} else if (isHttpRedirect(statusCode)) {
// statusCode==300
...
return loadDataWithRedirects(redirectUrl, redirects + 1, url, headers);
} else if (statusCode == INVALID_STATUS_CODE) {
throw new HttpException(statusCode);
} else {
throw new HttpException(urlConnection.getResponseMessage(), statusCode);
}
}
}
可以看到glide使用 urlConnection 发起网络请求,通过callback回掉结果。接下来看获取到数据后是如果处理的
class DecodeJob<R> implements DataFetcherGenerator.FetcherReadyCallback,
Runnable,Comparable<DecodeJob<?>>,Poolable {
@Override
public void onDataFetcherReady(Key sourceKey, Object data, DataFetcher<?> fetcher,
DataSource dataSource, Key attemptedKey) {
this.currentSourceKey = sourceKey; // 保存数据的 key
this.currentData = data; // 保存数据实体
this.currentFetcher = fetcher; // 保存数据的获取器
this.currentDataSource = dataSource;// 数据来源: url 为 REMOTE 类型的枚举, 表示从远程获取
...
if (Thread.currentThread() != currentThread) {
...
} else {
try {
// 1. 调用了 decodeFromData 获取资源
decodeFromRetrievedData();
} finally {
GlideTrace.endSection();
}
}
}
}
private void decodeFromRetrievedData() {
...
Resource<R> resource = null;
try {
// 1.解析资源
resource = decodeFromData(currentFetcher, currentData, currentDataSource);
} catch (GlideException e) {
e.setLoggingDetails(currentAttemptingKey, currentDataSource);
throwables.add(e);
}
if (resource != null) {
// 2.通知外界获取到资源
notifyEncodeAndRelease(resource, currentDataSource);
} else {
runGenerators();
}
}
可以看到对于获取到的数据, 首先要将其解码为 Resource 类型的资源, 然后再将资源返回给上层
我们先看看它是如何将数据解析成 Resource(非 Android 系统的 Resource) 资源的
class DecodeJob<R> implements DataFetcherGenerator.FetcherReadyCallback,
Runnable,Comparable<DecodeJob<?>>,Poolable {
private <Data> Resource<R> decodeFromData(DataFetcher<?> fetcher, Data data,
DataSource dataSource) throws GlideException {
try {
...
//调用了decodeFromFetcher
Resource<R> result = decodeFromFetcher(data, dataSource);
return result;
} finally {
fetcher.cleanup();
}
}
}
private <Data> Resource<R> decodeFromFetcher(Data data, DataSource dataSource)
throws GlideException {
// 1. 获取当前数据类的解析器 LoadPath
LoadPath<Data, ?, R> path = decodeHelper.getLoadPath((Class<Data>) data.getClass());
// 2. 通过解析器来解析来解析数据
return runLoadPath(data, dataSource, path);
}
private <Data, ResourceType> Resource<R> runLoadPath(Data data, DataSource dataSource,
LoadPath<Data, ResourceType, R> path) throws GlideException {
Options options = getOptionsWithHardwareConfig(dataSource);
// 2.1 根据数据类型获取一个数据重造器, 获取的数据为 InputStream, 因此它是一个 InputStreamRewinder 的实例
DataRewinder<Data> rewinder = glideContext.getRegistry().getRewinder(data);
try {
// 2.2 将解析资源的任务转移到了 LoadPath.load 方法中
return path.load(
rewinder, options, width, height, new DecodeCallback<ResourceType>(dataSource));
} finally {
rewinder.cleanup();
}
}
可以看到为了解析数据, 首先构建了一个 LoadPath, 然后创建了一个 InputStreamRewinder 类型的 DataRewinder, 最终将数据解析的操作到了 LoadPath.load 方法中
接下来看看这个LoadPath.load 做了哪些处理
public class LoadPath<Data, ResourceType, Transcode> {
public Resource<Transcode> load(DataRewinder<Data> rewinder, @NonNull Options options, int width,
int height, DecodePath.DecodeCallback<ResourceType> decodeCallback) throws GlideException {
List<Throwable> throwables = Preconditions.checkNotNull(listPool.acquire());
try {
return loadWithExceptionList(rewinder, options, width, height, decodeCallback, throwables);
} finally {
listPool.release(throwables);
}
}
}
private Resource<Transcode> loadWithExceptionList(DataRewinder<Data> rewinder,
@NonNull Options options,
int width, int height, DecodePath.DecodeCallback<ResourceType> decodeCallback,
List<Throwable> exceptions) throws GlideException {
Resource<Transcode> result = null;
// 遍历内部存储的 DecodePath 集合, 通过他们来解析数据
for (int i = 0, size = decodePaths.size(); i < size; i++) {
DecodePath<Data, ResourceType, Transcode> path = decodePaths.get(i);
try {
result = path.decode(rewinder, width, height, options, decodeCallback);
} catch (GlideException e) {
exceptions.add(e);
}
...
return result;
}
public class DecodePath<DataType, ResourceType, Transcode> {
public Resource<Transcode> decode(DataRewinder<DataType> rewinder, int width, int height,
@NonNull Options options, DecodeCallback<ResourceType> callback) throws GlideException {
// 1. 调用 decodeResource 将源数据解析成中间资源
Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
// 2. 调用 DecodeCallback.onResourceDecoded 处理中间资源
Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
// 3. 调用 ResourceTranscoder.transcode 将中间资源转为目标资源
return transcoder.transcode(transformed, options);
}
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有