Glide源码分析,2024疫情期间八家大厂的Android面试经历和真题整理

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移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

最后

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

腾讯、字节跳动、阿里、百度等BAT大厂 2019-2021面试真题解析

资料太多,全部展示会影响篇幅,暂时就先列举这些部分截图

…(img-10fXfWFO-1711937695544)]
[外链图片转存中…(img-v5KPzZEb-1711937695545)]
[外链图片转存中…(img-aaOibfbW-1711937695545)]
[外链图片转存中…(img-QiQX2dYq-1711937695545)]
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-SYP9lJgX-1711937695546)]

最后

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

[外链图片转存中…(img-f225dgs3-1711937695546)]

腾讯、字节跳动、阿里、百度等BAT大厂 2019-2021面试真题解析

[外链图片转存中…(img-MyymzyXK-1711937695546)]

资料太多,全部展示会影响篇幅,暂时就先列举这些部分截图

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

  • 17
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值