if (!isPaused) {
//未暂停,开始执行
request.begin();
} else {
//等待请求,List类型
// private final List<Request> pendingRequests = new ArrayList<>();
pendingRequests.add(request);
}
}
由源码可知,两个请求的类型不同,因为他们的状态不同,一个等待,一个执行。
* 调用`Request`的`begin`方法
package com.bumptech.glide.request;
/**
- A request that loads a resource for an {@link com.bumptech.glide.request.target.Target}.
*/
public interface Request {
/**
- Starts an asynchronous load.
*/
void begin();
…
}
通过源码发现,Request为一个接口,那么它的实现类是什么呢?
**上述铺垫的buildRequest方法告诉我们,它的实现类是SingleRequest。**
* 调用`SingleRequest`的`begin`方法
public void begin() {
...
status = Status.WAITING_FOR_SIZE;
//如果Target尺寸和这个一致
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
//准备
onSizeReady(overrideWidth, overrideHeight);
} else {
//获得target尺寸
target.getSize(this);
}
...
}
* 调用`SingleRequest`的`onSizeReady`方法
public void onSizeReady(int width, int height) {
...
//设置正在运行
status = Status.RUNNING;
...
//调用load方法,加载引擎
loadStatus = engine.load(
glideContext,
model,
requestOptions.getSignature(),
this.width,
this.height,
requestOptions.getResourceClass(),
transcodeClass,
priority,
requestOptions.getDiskCacheStrategy(),
requestOptions.getTransformations(),
requestOptions.isTransformationRequired(),
requestOptions.getOptions(),
requestOptions.isMemoryCacheable(),
requestOptions.getUseUnlimitedSourceGeneratorsPool(),
requestOptions.getOnlyRetrieveFromCache(),
this);
…
}
* 调用`Engine`的`load`方法
public 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,
Options options,
boolean isMemoryCacheable,
boolean useUnlimitedSourceExecutorPool,
boolean onlyRetrieveFromCache,
ResourceCallback cb) {
…
//key表示引擎的唯一索引
//通过工厂模式创建得到
EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,
resourceClass, transcodeClass, options);
//得到引擎资源
//先从内存缓存中找
EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
//缓存中有
if (cached != null) {
//直接准备资源
cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Loaded resource from cache", startTime, key);
}
return null;
}
//活动缓存,面向用户
//逻辑和内存缓存一致
EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
if (active != null) {
cb.onResourceReady(active, DataSource.MEMORY_CACHE);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Loaded resource from active resources", startTime, key);
}
return null;
}
//看看EngineJob是否存在在磁盘缓存中
EngineJob<?> current = jobs.get(key);
//存在则执行下列操作
if (current != null) {
current.addCallback(cb);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Added to existing load", startTime, key);
}
return new LoadStatus(cb, current);
}
//不存在,通过工厂模式创建
EngineJob<R> engineJob = engineJobFactory.build(key, isMemoryCacheable,
useUnlimitedSourceExecutorPool);
//DecodeJob同理
DecodeJob<R> decodeJob = decodeJobFactory.build(
glideContext,
model,
key,
signature,
width,
height,
resourceClass,
transcodeClass,
priority,
diskCacheStrategy,
transformations,
isTransformationRequired,
onlyRetrieveFromCache,
options,
engineJob);
//jobs里面没有,加入磁盘中
jobs.put(key, engineJob);
engineJob.addCallback(cb);
//将decodeJob放入engineJob中
//开启引擎
engineJob.start(decodeJob);
...
return new LoadStatus(cb, engineJob);
}
* 调用`EngineJob`的`start`方法
public void start(DecodeJob decodeJob) {
this.decodeJob = decodeJob;
GlideExecutor executor = decodeJob.willDecodeFromCache()
? diskCacheExecutor
: getActiveSourceExecutor();
//最终执行
executor.execute(decodeJob);
}
* 调用`GlideExecutor`的`execute`方法(线程池管理执行任务)
@Override
public void execute(Runnable command) {
if (executeSynchronously) {
command.run();
} else {
super.execute(command);
}
}
`execute`方法传入的参数是`DecodeJob`,在这个方法可知,里面的参数是`Runnable`类型的。然后执行`Runnable`的`run`方法,发现`Runnable`是个接口,那么它的具体实现类是什么呢?**就是它传入的参数了,是`DecodeJob`。**
* 调用`DecodeJob`的`run`方法
public void run() {
try {
//取消执行
if (isCancelled) {
notifyFailed();
return;
}
//不取消就执行这个方法
runWrapped();
} catch (RuntimeException e) {
...
}
}
* 执行`DecodeJob`的`runWrapped`方法
private void runWrapped() {
switch (runReason) {
case INITIALIZE:
stage = getNextStage(Stage.INITIALIZE);
//铺垫,是否配置缓存策略
//默认返回source
currentGenerator = getNextGenerator();
//执行
runGenerators();
break;
case SWITCH_TO_SOURCE_SERVICE:
//执行
runGenerators();
break;
case DECODE_DATA:
decodeFromRetrievedData();
break;
default:
throw new IllegalStateException("Unrecognized run reason: " + runReason);
}
}
**getNextGenerator方法中证明了下面的实现类是ResourceCacheGenerator,DataCacheGenerator, SourceGenerator(默认返回)中的。**
* 执行`DecodeJob`的`runGenerators`方法
private void runGenerators() {
...
while (!isCancelled && currentGenerator != null
//当前Generator的下一个方法
&& !(isStarted = currentGenerator.startNext())) {
stage = getNextStage(stage);
currentGenerator = getNextGenerator();
if (stage == Stage.SOURCE) {
reschedule();
return;
}
}
…
}
* 调用DataFetcherGenerator的`startNext`方法
**发现又是一个接口,因为只有SourceGenerator中有这个方法,所以实现类SourceGenerator。**
* 实现类实现`startNext`方法
public boolean startNext() {
if (dataToCache != null) {
Object data = dataToCache;
dataToCache = null;
cacheData(data);
}
if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
return true;
}
sourceCacheGenerator = null;
loadData = null;
boolean started = false;
while (!started && hasNextModelLoader()) {
//返回loadData
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;
}
* 调用loadData.fetcher.loadData,发现又是个接口,这里**找不到实现类**,那么就要看这个对象**如何得到**的。
`glide`有个注册机制,注册很多的组件,会把`HttpGlideUrlLoader`注册进来,进行网络请求。
loadData = helper.getLoadData()方法中有
```
LoadData<?> current =
modelLoader.buildLoadData(model, width, height, options);
```
通过注册机制可知:LoadData<?> current = HttpGlideUrlLoader;
* 调用里面的buildLoadData方法,发现是接口方法,然后找到实现类`HttpGlideUrlLoader`。
* 调用`HttpGlideUrlLoader`的`buildLoadData`方法
![在这里插入图片描述](https://img-blog.csdnimg.cn/33bcf4847d46402cb4748c597e2eeff0.png)
* 到HttpUrlFetcher类,进行网络请求
* 继续loadData,最后到`loadDataWithRedirects`方法,返回`InputSream`,得到数据流`InputStream`
public void loadData(
@NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) {
long startTime = LogTime.getLogTime();
try {
//得到数据Stream
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));
}
}
}
private InputStream loadDataWithRedirects(
URL url, int redirects, URL lastUrl, Map<String, String> headers) throws IOException {
...
//真正的网络请求,底层Socket
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);
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
最后
只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。
真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。
腾讯、字节跳动、阿里、百度等BAT大厂 2019-2021面试真题解析
资料太多,全部展示会影响篇幅,暂时就先列举这些部分截图
…(img-10fXfWFO-1711937695544)]
[外链图片转存中…(img-v5KPzZEb-1711937695545)]
[外链图片转存中…(img-aaOibfbW-1711937695545)]
[外链图片转存中…(img-QiQX2dYq-1711937695545)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-SYP9lJgX-1711937695546)]
最后
只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。
真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。
[外链图片转存中…(img-f225dgs3-1711937695546)]
腾讯、字节跳动、阿里、百度等BAT大厂 2019-2021面试真题解析
[外链图片转存中…(img-MyymzyXK-1711937695546)]
资料太多,全部展示会影响篇幅,暂时就先列举这些部分截图