Glide源码解析三部曲-之三into(写到昏天黑地版)

205 阅读11分钟

1、时序图&流程图

2、第三步into的简略分析

  • 上回说到Glide.whith(context).load("xxxxxx");返回了RequestBuilder
  • 那么这回就是Glide.whit(context).load("xxxxxx").into(view);也就是into的事情了

2.1、拿到getScaleType类型的属性,Imageview的Imageview的 。clone一个进行配置

@NonNull
public ViewTarget<ImageView, TranscodeType> into(@NonNull

ImageView view) {

Util.assertMainThread();

Preconditions.checkNotNull(view);

// 根据 ImageView 布局中的 scaleType 来重构 requestOptions

BaseRequestOptions<?> requestOptions = this;

if (!requestOptions.isTransformationSet()

&& requestOptions.isTransformationAllowed()

&& view.getScaleType() != null) {

//如果在 xml ImageView 节点中 没有设置 scaleType 那么默认在构造函数

中进行了初始化为 mScaleType = ScaleType.FIT_CENTER;

switch (view.getScaleType()) {

.....

case FIT_CENTER:

case FIT_START:

case FIT_END:

//这里用到了克隆(原型设计模式),选择一个 居中合适 显示的方案,同学

们会发现,到处都是设计模式,它不是为了装B哦

requestOptions =

requestOptions.clone().optionalFitCenter();

break;

....

}

}

//调用 into 重载函数,创建一个 ViewTarget

return into(

//调用 buildImageViewTarget 构建一个 ImageView 类型的

Target(Bitmap/Drawable)

glideContext.buildImageViewTarget(view, transcodeClass),

/*targetListener=*/ null,

requestOptions,

Executors.mainThreadExecutor());

}

2.2、调用into重载继续构造

  • 先看下glideContext.buildeImageViewTarget怎么构建出来的
  • 只有调用了 asBitmap 才会执行生 BitmapImageViewTarget ,所以这里我们关注 Drawable 类型就行了
ImageViewtarget

@NonNull

public <X> ViewTarget<ImageView, X> buildImageViewTarget(

@NonNull ImageView imageView, @NonNull Class<X>

transcodeClass) {

//调用 工厂模式 根据 transcodeClass 生成出一个对应的

ImageViewTarget

return imageViewTargetFactory.buildTarget(imageView,

transcodeClass);

}

public class ImageViewTargetFactory {

@NonNull

@SuppressWarnings("unchecked")

public <Z> ViewTarget<ImageView, Z> buildTarget(@NonNull

ImageView view,

@NonNull Class<Z> clazz) {

//如果目标的编码类型属于 Bitmap 那么就创建一个 Bitmap 类型的

ImageViewTarget

if (Bitmap.class.equals(clazz)) {

return (ViewTarget<ImageView, Z>) new

BitmapImageViewTarget(view);

////如果目标的编码类型属于 Drawable 那么就创建一个 Drawable 类型的

ImageViewTarget

} 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)");

}

}

}

2.3、DrawableImageViewTarget

  • 最终在view.setImageDrawable(resource);中设置了view的source
public class DrawableImageViewTarget extends

ImageViewTarget<Drawable> {

public DrawableImageViewTarget(ImageView view) {

super(view);

}

@SuppressWarnings({"unused", "deprecation"})

@Deprecated

public DrawableImageViewTarget(ImageView view, boolean

waitForLayout) {

super(view, waitForLayout);

}

@Override

protected void setResource(@Nullable Drawable resource) {

view.setImageDrawable(resource);

}

}

DrawableImageViewTarget 继承的是ImageViewTarget 重写的 setResource 函数

2.4、以上内容核心

2.4.1、位target buildeRequets构建一个GlideRequets请求
2.4.2、将构建出来的Requetst交于RequestManager来执行,主要用于对请求的管理封装
private <Y extends Target<TranscodeType>> Y into(

@NonNull Y target,

@Nullable RequestListener<TranscodeType> targetListener,

BaseRequestOptions<?> options,

Executor callbackExecutor) {

Preconditions.checkNotNull(target);

//这里的 isModelSet 是在 load 的时候赋值为 true 的,所以不会抛异常

if (!isModelSet) {

throw new IllegalArgumentException("You must call #load()

before calling #into()");

}

//为这个 http://xxx.png 生成一个 Glide request 请求

Request request = buildRequest(target, targetListener,

options, callbackExecutor);

//相当于拿到上一个请求

Request previous = target.getRequest();

//下面的几行说明是否与上一个请求冲突,一般不用管 直接看下面 else 判断

if (request.isEquivalentTo(previous)

&& !isSkipMemoryCacheWithCompletePreviousRequest(options,

previous)) {

request.recycle();

if (!Preconditions.checkNotNull(previous).isRunning()) {

previous.begin();

}

return target;

}

//清理掉目标请求管理

requestManager.clear(target);

//重新为目标设置一个 Glide request 请求

target.setRequest(request);

//最后是调用 RequestManager 的 track 来执行目标的 Glide request 请

求

requestManager.track(target, request);

return target;

}

3、into详细讲解

3.1、在RequestBuilder中,构建Request,

3.1.1、RequestBuilder中调用SingleRequest.obtain来构建Request对象,开始就是配置一些属性。
private Request buildRequest(

Target<TranscodeType> target,

@Nullable RequestListener<TranscodeType> targetListener,

BaseRequestOptions<?> requestOptions,

Executor callbackExecutor) {

return buildRequestRecursive(

target,

targetListener,

/*parentCoordinator=*/ null,

transitionOptions,

requestOptions.getPriority(),

requestOptions.getOverrideWidth(),

requestOptions.getOverrideHeight(),

requestOptions,

callbackExecutor);

}

``````省略若干

private Request obtainRequest(

Target<TranscodeType> target,

RequestListener<TranscodeType> targetListener,

BaseRequestOptions<?> requestOptions,

RequestCoordinator requestCoordinator,

TransitionOptions<?, ? super TranscodeType>

transitionOptions,Priority priority,

int overrideWidth,

int overrideHeight,

Executor callbackExecutor) {

return SingleRequest.obtain(

context,

glideContext,

model,

transcodeClass,

requestOptions,

overrideWidth,

overrideHeight,

priority,

target,

targetListener,

requestListeners,

requestCoordinator,

glideContext.getEngine(),

transitionOptions.getTransitionFactory(),

callbackExecutor);

}

3.1.2、 requestManager.track(target, request);
  • 先为 requests 添加一个请求,看看是否是停止状态,如果不是就调 用 request.begin(); 执行。??
//这里对当前 class 加了一个同步锁避免线程引起的安全性

synchronized void track(@NonNull Target<?> target, @NonNull

Request request) {

//添加一个目标任务

targetTracker.track(target);

//执行 Glide request

requestTracker.runRequest(request);

}

  


public void runRequest(@NonNull Request request) {

//添加一个请求

requests.add(request);

//是否暂停

if (!isPaused) {

//没有暂停,开始调用 Request begin 执行

request.begin();

} else {

//如果调用了 暂停,清理请求

request.clear();

pendingRequests.add(request);

}

}

3.2、RequestManager#runRequest->request#begin

  • Request 的实现类是 SingleRequest
`@Override`

`public synchronized void begin() {`

`assertNotCallingCallbacks();`

`stateVerifier.throwIfRecycled();`

`startTime = LogTime.getLogTime();`

`if (model == null) {`

`//检查外部调用的尺寸是否有效`

`if (Util.isValidDimensions(overrideWidth, overrideHeight))`

`{`

`width = overrideWidth;`

`height = overrideHeight;`

`}`

`//失败的回调`

`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 {`

`target.getSize(this);`

`}`

`//这里是刚刚开始执行的回调,相当于显示开始的进度`

`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));`

`}`

`}`

3.3 SingleRequest#onsizeReady->engine#load

  • 终于到了engine#load
public synchronized void onSizeReady(int width, int height) {

stateVerifier.throwIfRecycled();

....//都是一些初始化状态,配置属性,我们不用管。

loadStatus =

//加载

engine.load(

glideContext,

model,

requestOptions.getSignature(),

this.width,

this.height,

requestOptions.getResourceClass(),

transcodeClass,

priority,

requestOptions.getDiskCacheStrategy(),

load:

requestOptions.getTransformations(),

requestOptions.isTransformationRequired(),

requestOptions.isScaleOnlyOrNoTransform(),

requestOptions.getOptions(),

requestOptions.isMemoryCacheable(),

requestOptions.getUseUnlimitedSourceGeneratorsPool(),

requestOptions.getUseAnimationPool(),

requestOptions.getOnlyRetrieveFromCache(),

this,

callbackExecutor);

3.3、engine#load->Engine

  • 先构建请求或者缓存KEY
  • 根据KEY找内存缓存、活动缓存,如果有就调用onResourceReady回调表示数据准备好了
  • 如果没有找到就通过EngineJob.START
public synchronized <R> LoadStatus load(

GlideContext glideContext,

Object model,

Key signature,

int width,

int height,

Class<?> resourceClass,

Class<R> transcodeClass,

Priority priority,

DiskCacheStrategy diskCacheStrategy,

Map<Class<?>, Transformation<?>> transformations,

boolean isTransformationRequired,

boolean isScaleOnlyOrNoTransform,

Options options,

boolean isMemoryCacheable,

boolean useUnlimitedSourceExecutorPool,

boolean useAnimationPool,

boolean onlyRetrieveFromCache,

ResourceCallback cb,

Executor callbackExecutor) {

//拿到缓存或者请求的 key

EngineKey key = keyFactory.buildKey(model, signature, width,

height, transformations,

resourceClass, transcodeClass, options);

//根据 key 拿到活动缓存中的资源

EngineResource<?> active = loadFromActiveResources(key,

isMemoryCacheable);

//如果 ActiveResources 活动缓存中有就回调出去

if (active != null) {

cb.onResourceReady(active, DataSource.MEMORY_CACHE);

享学课堂

return null;

}

//尝试从 LruResourceCache 中找寻这个资源

EngineResource<?> cached = loadFromCache(key,

isMemoryCacheable);

if (cached != null) {

//如果内存缓存 Lru 中资源存在回调出去

cb.onResourceReady(cached, DataSource.MEMORY_CACHE);

return null;

}

//------------- 走到这里说明活动缓存 跟内存 缓存都没有找到 ----------

-

//根据 Key 看看缓存中是否正在执行

EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);

if (current != null) {

//如果正在执行,把数据回调出去

current.addCallback(cb, callbackExecutor);

if (VERBOSE_IS_LOGGABLE) {

logWithTimeAndKey("Added to existing load", startTime,

key);

}

return new LoadStatus(cb, current);

}

// -------------- 走到这里说明是一个新的任务 ---------------

// -------------- 构建新的请求任务 ---------------

EngineJob<R> engineJob =

engineJobFactory.build(

key,

isMemoryCacheable,

useUnlimitedSourceExecutorPool,

useAnimationPool,

onlyRetrieveFromCache);

DecodeJob<R> decodeJob =

decodeJobFactory.build(

glideContext,

model,

key,

signature,

width,

height,

resourceClass,

transcodeClass,

priority,

diskCacheStrategy,

transformations,

isTransformationRequired,

isScaleOnlyOrNoTransform,

onlyRetrieveFromCache,

options,

engineJob);

//把当前需要执行的 key 添加进缓存

jobs.put(key, engineJob);

//执行任务的回调

engineJob.addCallback(cb, callbackExecutor);

//开始执行。

engineJob.start(decodeJob);

return new LoadStatus(cb, engineJob);

}

通过 engine.load 这个函数里面的逻辑,我们可以总结3点:

  1. 先构建请求或者缓存 KEY ;

  2. 根据 KEY 从内存缓存中查找对应的资源数据(ActiveResources(活动缓存,内部

是一个 Map 用弱引用持有),LruResourceCache),如果有就回调 对应监听的

onResourceReady 表示数据准备好了。

  1. 从执行缓存中查找对应 key 的任务

  2. 如果找到了,就说明已经正在执行了,不用重复执行。

  3. 没有找到,通过 EngineJob.start 开启一个新的请求任务执行。

同学们下面我们就来看下 engineJob.start 具体执行逻辑:

3.4、engineJob#start->executor#execute(decodeJob);


-   通过 DecodeJob 源码得知,它是实现的 Runnable 接口,这里 GlideExecutor 线程池开始执行,就会启动 DecodeJob 的 run 函数,我们跟踪 run 的实现:

public synchronized void start(DecodeJob<R> decodeJob) {

this.decodeJob = decodeJob;

//拿到 Glide 执行的线程池

GlideExecutor executor = decodeJob.willDecodeFromCache()

? diskCacheExecutor

: getActiveSourceExecutor();

//开始执行

executor.execute(decodeJob);

}

3.5、DecodeJob#RUN

  • 核心走到runWrapped
class DecodeJob<R> implements

DataFetcherGenerator.FetcherReadyCallback,

Runnable,

Comparable<DecodeJob<?>>,

Poolable {

// 线程执行调用 run

@Override

public void run() {

GlideTrace.beginSectionFormat("DecodeJob#run(model=%s)",

model);

DataFetcher<?> localFetcher = currentFetcher;

try {

//是否取消了当前请求

if (isCancelled) {

notifyFailed();

return;

}

//执行

runWrapped();

} catch (CallbackException e) {

.....//一些错误回调

}

}
3.5.1、runWrapped
  • //获取资源状态
  • stage = getNextStage(Stage.INITIALIZE);
  • //根据当前资源状态,获取资源执行器 currentGenerator = getNextGenerator();
  • //执行
  • runGenerators();
private void runWrapped() {

switch (runReason) {

case INITIALIZE:

//获取资源状态

stage = getNextStage(Stage.INITIALIZE);

//根据当前资源状态,获取资源执行器

currentGenerator = getNextGenerator();

//执行

runGenerators();

break;

...

}

}

private Stage getNextStage(Stage current) {

switch (current) {

case INITIALIZE:

//如果外部调用配置了资源缓存策略,那么返回 Stage.RESOURCE_CACHE

//否则继续调用 Stage.RESOURCE_CACHE 执行。

return diskCacheStrategy.decodeCachedResource()

? Stage.RESOURCE_CACHE :

getNextStage(Stage.RESOURCE_CACHE);

case RESOURCE_CACHE:

//如果外部配置了源数据缓存,那么返回 Stage.DATA_CACHE

//否则继续调用 getNextStage(Stage.DATA_CACHE)

return diskCacheStrategy.decodeCachedData()

? Stage.DATA_CACHE : getNextStage(Stage.DATA_CACHE);

case DATA_CACHE:

//如果只能从缓存中获取数据,则直接返回 FINISHED,否则,返回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);

}

}

3.5.2、runGenerators
  • 调用 DataFetcherGenerator.startNext() 判断是否是属于开始执行的任 务
  • Stage.RESOURCE_CACHE【状态标记】 ---- 从磁盘中获取缓存的资源数据【作用】 -
  • ResourceCacheGenerator【执行器】
  • Stage.DATA_CACHE【状态标记】 ---- 从磁盘中获取缓存的源数据【作用】
  • DataCacheGenerator【执行器】 Stage.SOURCE【状态标记】 --- 一次新的请求任务 --- SourceGenerator【执行器】
private void runGenerators() {

currentThread = Thread.currentThread();

startFetchTime = LogTime.getLogTime();

boolean isStarted = false;

//判断是否取消,是否开始

//调用 DataFetcherGenerator.startNext() 判断是否是属于开始执行的任while (!isCancelled && currentGenerator != null

&& !(isStarted = currentGenerator.startNext())) {

....

}
3.5.3、currentGenerator#startNext->DataCacheGenerator

//获取一个 ModelLoad 加载器

loadData = helper.getLoadData().get(loadDataListIndex++);

//使用加载器中的 fetcher 根据优先级加载数据loadData.fetcher.loadData(helper.getPriority(), this);

@Override

public boolean startNext() {

...

loadData = null;

boolean started = false;

while (!started && hasNextModelLoader()) {

//获取一个 ModelLoad 加载器

loadData = helper.getLoadData().get(loadDataListIndex++);

if (loadData != null&&

(helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.g

etDataSource())

||

helper.hasLoadPath(loadData.fetcher.getDataClass()))) {

started = true;

//使用加载器中的 fetcher 根据优先级加载数据

loadData.fetcher.loadData(helper.getPriority(), this);

}

}

return started;

}
3.5.3.1、helper.getLoadData()

3.6、DataCacheGenerator 下helper.getLoadData()


//开始构建加载器

modelLoader.buildLoadData(model, width, height,

options);

List<LoadData<?>> getLoadData() {

if (!isLoadDataSet) {

isLoadDataSet = true;

loadData.clear();

//从 Glide 注册的 Model 来获取加载器(注册是在 Glide 初始化的时候通

过 registry

// .append()添加的)

List<ModelLoader<Object, ?>> modelLoaders =

glideContext.getRegistry().getModelLoaders(model);

for (int i = 0, size = modelLoaders.size(); i < size; i++)

{

ModelLoader<Object, ?> modelLoader = modelLoaders.get(i);

LoadData<?> current =

//😄开始构建加载器########################################

modelLoader.buildLoadData(model, width, height,

options);

//如果架子啊器不为空,那么添加进临时缓存

if (current != null) {

loadData.add(current);

}

}

}

return loadData;

}

3.6.1、😆modelLoader#buildLoadData ->modelLoader 也就是HttpGlideUrlLoader 返回了loadData


@Override

public LoadData<InputStream> buildLoadData(@NonNull GlideUrl

model, int width, int height,

@NonNull Options options) {

GlideUrl url = model;

if (modelCache != null) {

url = modelCache.get(model, 0, 0);

if (url == null) {

modelCache.put(model, 0, 0, model);

url = model;

}

}

int timeout = options.get(TIMEOUT);

// 【同学们注意:之前有开发者看了一周Glide源码,也找不到网络请求的地方,我

们现在就已经找到了,很伟大了,可以给自己鼓掌】

return new LoadData<>(url, new HttpUrlFetcher(url, timeout));

}

  
3.6.2、loadData#fetch#loadData->HttpUrlFetcher->通过callback.onDataReady(result)回到DataCahceGenerator

//http 请求,返回一个 InputStream 输入流

InputStream result =

@Override

public void loadData(@NonNull Priority priority,

@NonNull DataCallback<? super InputStream> callback) {

long startTime = LogTime.getLogTime();

try {

//http 请求,返回一个 InputStream 输入流

InputStream result =

loadDataWithRedirects(glideUrl.toURL(), 0, null,

glideUrl.getHeaders());

//将 InputStream 以回调形式回调出去

callback.onDataReady(result);

} catch (IOException e) {

callback.onLoadFailed(e);

} finally {

...

}

}

3.6.2.1、loadDataWithRedirects
  • HttpURLConnection 作为 Glide 底层成网络请求的。请求成功之后直接返回的是一个输入流,最后会通过 onDataReady.回调到SourceGenerator
private InputStream loadDataWithRedirects(URL url, int

redirects, URL lastUrl,

Map<String, String> headers) throws IOException {

if (redirects >= MAXIMUM_REDIRECTS) {

throw new HttpException("Too many (> " + MAXIMUM_REDIRECTS

+ ") redirects!");

} else {

try {

if (lastUrl != null &&

url.toURI().equals(lastUrl.toURI())) {

throw new HttpException("In re-direct loop");

}

} catch (URISyntaxException e) {

// Do nothing, this is best effort.

}

}

urlConnection = connectionFactory.build(url);

for (Map.Entry<String, String> headerEntry :

headers.entrySet()) {

urlConnection.addRequestProperty(headerEntry.getKey(),

headerEntry.getValue());

}

urlConnection.setConnectTimeout(timeout);

urlConnection.setReadTimeout(timeout);

urlConnection.setUseCaches(false);

urlConnection.setDoInput(true);

urlConnection.setInstanceFollowRedirects(false);

urlConnection.connect();

stream = urlConnection.getInputStream();

if (isCancelled) {

return null;

}

final int statusCode = urlConnection.getResponseCode();

if (isHttpOk(statusCode)) {

return getStreamForSuccessfulRequest(urlConnection);

}

...//抛的异常我们暂时先不管

}
3.6.3、SourceGenerator#onDataReady
@Override

public void onDataReady(Object data) {

DiskCacheStrategy diskCacheStrategy =

helper.getDiskCacheStrategy();

if (data != null &&

diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource(

))) {

dataToCache = data;

// 😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄 ResourceCallback cb

cb.reschedule();

} else {

//这里会有 else 因为我们没有配置缓存

cb.onDataFetcherReady(loadData.sourceKey, data,

loadData.fetcher,

loadData.fetcher.getDataSource(), originalKey);

}

}
3.6.4、DataCacheGenerator#cb.onDataFetcherReady(也就是 RCallback ) 然后通过callback回到->DecodeJob

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; //返回的数据执行器,这里可以理解

为 HttpUrlFetcher

this.currentDataSource = dataSource; //数据来源 url

this.currentAttemptingKey = attemptedKey;

if (Thread.currentThread() != currentThread) {

runReason = RunReason.DECODE_DATA;

callback.reschedule(this);

} else {

GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");

try {

//解析返回回来的数据

decodeFromRetrievedData();

} finally {

GlideTrace.endSection();

}

}

}

...

}

//解析返回的数据

private void decodeFromRetrievedData() {

Resource<R> resource = null;

try {

// 调用 decodeFrom 解析 数据;HttpUrlFetcher , InputStream ,

currentDataSource

resource = decodeFromData(currentFetcher, currentData,

currentDataSource);

} catch (GlideException e) {

e.setLoggingDetails(currentAttemptingKey,

currentDataSource);

throwables.add(e);

}

//解析完成后,通知下去

if (resource != null) {

notifyEncodeAndRelease(resource, currentDataSource);

} else {

runGenerators();

}

}

3.7、DecodeJob#decodeFromData 解码->LoadPath

private <Data> Resource<R> decodeFromData(DataFetcher<?>

fetcher, Data data,

DataSource dataSource) throws GlideException {

...

Resource<R> result = decodeFromFetcher(data, dataSource);

....

return result;

} finally {

fetcher.cleanup();

}

}

@SuppressWarnings("unchecked")

private <Data> Resource<R> decodeFromFetcher(Data data,

DataSource dataSource)

throws GlideException {

LoadPath.load 方法中 ,接下来看下 LoadPath.load 方法的具体逻辑操作:

//获取当前数据类的解析器 LoadPath

LoadPath<Data, ?, R> path =

decodeHelper.getLoadPath((Class<Data>) data.getClass());

//通过 LoadPath 解析器来解析数据

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);

//因为这里返回的是一个 InputStream 所以 这里拿到的是

InputStreamRewinder

DataRewinder<Data> rewinder =

glideContext.getRegistry().getRewinder(data);

try {

//将解析资源的任务转移到 Load.path 方法中

return path.load(

rewinder, options, width, height, new

DecodeCallback<ResourceType>(dataSource));

} finally {

rewinder.cleanup();

}

}
3.7.1、path.load
  • 为了解析数据首先构建一个 LoadPath, 然后创建一个InputStreamRewinder 类型的 DataRewinder, 最终将数据解析的操作放到了LoadPath.load 方法中 ,接下来看下 LoadPath.load 方法的具体逻辑操作
public Resource<Transcode> load(DataRewinder<Data> rewinder,

@NonNull Options options, int width,

int height, DecodePath.DecodeCallback<ResourceType>

decodeCallback) throws GlideException {

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) {

...

}

...

return result;

}

3.8、LoadPath#path.decode 转码的地方


public Resource<Transcode> decode(DataRewinder<DataType>

rewinder, int width, int height,

@NonNull Options options, DecodeCallback<ResourceType>

callback) throws GlideException {

//调用 decodeResourec 将数据解析成中间资源

Resource<ResourceType> decoded = decodeResource(rewinder,

width, height, options);

//解析完数据回调出去

Resource<ResourceType> transformed =

callback.onResourceDecoded(decoded);

//转换资源为目标资源

return transcoder.transcode(transformed, options);

}

3.9、DecodePath#DecodeResource

  • 第一大步:deResource 将源数据解析成资源(源数据: InputStream, 中间产物:Bitmap)
  • 第二大步:调用 DecodeCallback.onResourceDecoded 处理资源
  • 第三大步:调用 ResourceTranscoder.transcode 将资源转为目标资源(目标资源类型: Drawable)
@NonNull

private Resource<ResourceType>

decodeResource(DataRewinder<DataType> rewinder, int width,

int height, @NonNull Options options) throws GlideException

{

...

try {

return decodeResourceWithList(rewinder, width, height,

options, exceptions);

} finally {

...

}

}

@NonNull

private Resource<ResourceType>

decodeResourceWithList(DataRewinder<DataType> rewinder, int

width,

int height, @NonNull Options options, List<Throwable>

exceptions) throws GlideException {

Resource<ResourceType> result = null;

//noinspection ForLoopReplaceableByForEach to improve perf

for (int i = 0, size = decoders.size(); i < size; i++) {

ResourceDecoder<DataType, ResourceType> decoder =

decoders.get(i);

try {

DataType data = rewinder.rewindAndGet();

if (decoder.handles(data, options)) {

data = rewinder.rewindAndGet();

// 调用 ResourceDecoder.decode 解析数据

result = decoder.decode(data, width, height, options);

}

} catch (IOException | RuntimeException | OutOfMemoryError

e) {

...

}

return result;

}
3.9.1、decode#decode
@Override

public Resource<Bitmap> decode(@NonNull InputStream source, int

width, int height,

@NonNull Options options)

throws IOException {

// Use to fix the mark limit to avoid allocating buffers that

fit entire images.

final RecyclableBufferedInputStream bufferedStream;

final boolean ownsBufferedStream;

....

try {

// 根据请求配置来对数据进行采样压缩,获取一个 Resource<Bitmap>

return downsampler.decode(invalidatingStream, width,

height, options, callbacks);

} finally {

....

}

}

3.10、StreamBitmapDecoder#downsampler.decode

StreamBitmapDecoder

public Resource<Transcode> decode(DataRewinder<DataType>

rewinder, int width, int height,

@NonNull Options options, DecodeCallback<ResourceType>

callback) throws GlideException {

//第一步: 调用 decodeResourec 将数据解析成中间资源 Bitmap

Resource<ResourceType> decoded = decodeResource(rewinder,

width, height, options);

//第二步: 解析完数据回调出去

Resource<ResourceType> transformed =

callback.onResourceDecoded(decoded);

//第三步: 转换资源为目标资源 Bitmap to Drawable

return transcoder.transcode(transformed, options);

}
3.10.1、返回 给DecodePath

callback.onResourceDecoded->DecodeJob

3.11、DecodeJob

3.11.1、onResourceDecoded
3.11.2、notifyEncodeAndRelease
3.11.3、notifyComplete
3.11.4、callback.onResourceReady#EngineJob

3.12、EngineJob

3.12.1、notifycallbacksOfResult
3.12.2、CallResourceReady
3.12.3、 notifyCallbacksOfResult
3.12.4、 entry.executor.execute(new CallResourceReady(entry.cb));
3.12.5、 callCallbackOnResourceReady
3.12.6、 cb.onResourceReady(engineResource, dataSource);-》SingleRequest

3.13、SingleRequest

3.13.1、onResourceReady
3.13.2、onResourceReady
3.13.3、target.onResourceReady->ImageViewTarget

3.14、ImageViewTarget

3.14.1、setResourceInternal
3.14.1、setResource->DrawableImageViewTarget

3.15、DrawableImageViewTarget

3.15.1、setResource
3.15.2、view.setImageDrawable(resource)