Glide图片加载框架是如何确定图片加载的生命周期

这篇具有很好参考价值的文章主要介绍了Glide图片加载框架是如何确定图片加载的生命周期。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Glide基本使用方式:Glide.with(context).load(url).into(imageView);

Glide 最基本的用法就是三步走:先with(),再load(),最后into()。

那么我们开始一步步阅读这三步走的源码,先从with()看起。

1. with()
with()方法是Glide 类中的一组静态方法,它有好几个方法重载,我们来看一下Glide 类中所
有with()方法的方法重载:

public class Glide {
...
public static RequestManager with(Context context) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(context);
}
public static RequestManager with(Activity activity) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(activity);
}
public static RequestManager with(FragmentActivity activity) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(activity);
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static RequestManager with(android.app.Fragment fragment) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(fragment);
}
public static RequestManager with(Fragment fragment) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(fragment);
}
}


可以看到,with()方法的重载种类非常多,既可以传入Activity,也可以传入Fragment 或者
是Context。每一个with()方法重载的代码都非常简单,都是先调用RequestManagerRetriever
的静态get()方法得到一个RequestManagerRetriever 对象,这个静态get()方法就是一个单例
实现,没什么需要解释的。然后再调用RequestManagerRetriever 的实例get()方法,去获取
RequestManager 对象。
而RequestManagerRetriever 的实例get()方法中的逻辑是什么样的呢?我们一起来看一看:

public class RequestManagerRetriever implements Handler.Callback {
private static final RequestManagerRetriever INSTANCE = new RequestManagerRetriever();
private volatile RequestManager applicationManager;
...
/**
* Retrieves and returns the RequestManagerRetriever singleton.
*/
public static RequestManagerRetriever get() {
return INSTANCE;
}
private RequestManager getApplicationManager(Context context) {
// Either an application context or we're on a background thread.
if (applicationManager == null) {
synchronized (this) {
if (applicationManager == null) {
// Normally pause/resume is taken care of by the fragment we add to
the fragment or activity.
// However, in this case since the manager attached to the application
will not receive lifecycle
// events, we must force the manager to start resumed using
ApplicationLifecycle.
applicationManager = new
RequestManager(context.getApplicationContext(),
new ApplicationLifecycle(), new
EmptyRequestManagerTreeNode());
}
}
}
return applicationManager;
}
public RequestManager get(Context context) {
if (context == null) {
throw new IllegalArgumentException("You cannot start a load on a null Context");
} else if (Util.isOnMainThread() && !(context instanceof Application)) {
if (context instanceof FragmentActivity) {
return get((FragmentActivity) context);
} else if (context instanceof Activity) {
return get((Activity) context);
} else if (context instanceof ContextWrapper) {
return get(((ContextWrapper) context).getBaseContext());
}
}
return getApplicationManager(context);
}
public RequestManager get(FragmentActivity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
FragmentManager fm = activity.getSupportFragmentManager();
return supportFragmentGet(activity, fm);
}
}
public RequestManager get(Fragment fragment) {
if (fragment.getActivity() == null) {
throw new IllegalArgumentException("You cannot start a load on a fragment
before it is attached");
}
if (Util.isOnBackgroundThread()) {
return get(fragment.getActivity().getApplicationContext());
} else {
FragmentManager fm = fragment.getChildFragmentManager();
return supportFragmentGet(fragment.getActivity(), fm);
}
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public RequestManager get(Activity activity) {
if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT <
Build.VERSION_CODES.HONEYCOMB) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
android.app.FragmentManager fm = activity.getFragmentManager();
return fragmentGet(activity, fm);
}
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
private static void assertNotDestroyed(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 &&
activity.isDestroyed()) {
throw new IllegalArgumentException("You cannot start a load for a destroyed
activity");
}
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public RequestManager get(android.app.Fragment fragment) {
if (fragment.getActivity() == null) {
throw new IllegalArgumentException("You cannot start a load on a fragment
before it is attached");
}
if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT <
Build.VERSION_CODES.JELLY_BEAN_MR1) {
return get(fragment.getActivity().getApplicationContext());
} else {
android.app.FragmentManager fm = fragment.getChildFragmentManager();
return fragmentGet(fragment.getActivity(), fm);
}
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
RequestManagerFragment getRequestManagerFragment(final
android.app.FragmentManager fm) {
RequestManagerFragment current = (RequestManagerFragment)
fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
current = pendingRequestManagerFragments.get(fm);
if (current == null) {
current = new RequestManagerFragment();
pendingRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current,
FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER,
fm).sendToTarget();
}
}
return current;
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
RequestManager fragmentGet(Context context, android.app.FragmentManager fm) {
RequestManagerFragment current = getRequestManagerFragment(fm);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
requestManager = new RequestManager(context, current.getLifecycle(),
current.getRequestManagerTreeNode());
current.setRequestManager(requestManager);
}
return requestManager;
}
SupportRequestManagerFragment getSupportRequestManagerFragment(final
FragmentManager fm) {
SupportRequestManagerFragment current = (SupportRequestManagerFragment)
fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
current = pendingSupportRequestManagerFragments.get(fm);
if (current == null) {
current = new SupportRequestManagerFragment();
pendingSupportRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current,
FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER,
fm).sendToTarget();
}
}
return current;
}
RequestManager supportFragmentGet(Context context, FragmentManager fm) {
SupportRequestManagerFragment current =
getSupportRequestManagerFragment(fm);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
requestManager = new RequestManager(context, current.getLifecycle(),
current.getRequestManagerTreeNode());
current.setRequestManager(requestManager);
}
return requestManager;
}
...
}


上述代码虽然看上去逻辑有点复杂, 但是将它们梳理清楚后还是很简单的。
RequestManagerRetriever 类中看似有很多个get()方法的重载,什么Context 参数,Activity
参数,Fragment 参数等等,实际上只有两种情况而已,即传入Application 类型的参数,和
传入非Application 类型的参数。


我们先来看传入Application 参数的情况。如果在Glide.with()方法中传入的是一个Application
对象,那么这里就会调用带有Context 参数的get()方法重载,然后会在第44 行调用
getApplicationManager()方法来获取一个RequestManager 对象。其实这是最简单的一种情况,
因为Application 对象的生命周期即应用程序的生命周期,因此Glide 并不需要做什么特殊的
处理,它自动就是和应用程序的生命周期是同步的,如果应用程序关闭的话,Glide 的加载
也会同时终止。


接下来我们看传入非Application 参数的情况。不管你在Glide.with()方法中传入的是Activity、
FragmentActivity、v4 包下的Fragment、还是app 包下的Fragment,最终的流程都是一样的,
那就是会向当前的Activity 当中添加一个隐藏的Fragment。具体添加的逻辑是在上述代码的
第117 行和第141 行,分别对应的app 包和v4 包下的两种Fragment 的情况。那么这里为什
么要添加一个隐藏的Fragment 呢?因为Glide 需要知道加载的生命周期。很简单的一个道理,
如果你在某个Activity 上正在加载着一张图片,结果图片还没加载出来,Activity 就被用户关
掉了,那么图片还应该继续加载吗?当然不应该。可是Glide 并没有办法知道Activity 的生
命周期,于是Glide 就使用了添加隐藏Fragment 的这种小技巧,因为Fragment 的生命周期
和Activity 是同步的,如果Activity 被销毁了,Fragment 是可以监听到的,这样Glide 就可以
捕获这个事件并停止图片加载了。


这里额外再提一句,从第48 行代码可以看出,如果我们是在非主线程当中使用的Glide,那
么不管你是传入的Activity 还是Fragment,都会被强制当成Application 来处理。不过其实这
就属于是在分析代码的细节了。


总体来说, 第一个with() 方法的源码还是比较好理解的。其实就是为了得到一个
RequestManager 对象而已,然后Glide 会根据我们传入with()方法的参数来确定图片加载的
生命周期,并没有什么特别复杂的逻辑。文章来源地址https://www.toymoban.com/news/detail-427877.html

到了这里,关于Glide图片加载框架是如何确定图片加载的生命周期的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android使用Glide类加载服务器中的图片

    Glide类用于从服务器中获取图片并加载进ImageView。 一、添加依赖 Glide为 第三方框架 ,使用时需添加依赖: 在 Gradle Scripts / build.gradle(Module:app) / dependencies方法 中添加 添加后会下载。 二、获取权限 获取服务器中的图片需要 申请(静态声明)网络权限 ,在清单文件中添加 三、

    2024年02月06日
    浏览(43)
  • Android之Glide图片框架分析

    使用简单,链式调用,API简洁。with、load、into三步走就可以加载图片 生命周期自动绑定,根据绑定的Activity或者Fragment生命周期管理图片请求 高效处理Bitmap。支持bitmap的复用和主动回收,减少系统回收压力。 占用内存小(使用RGB565的格式),RGB8888每个像素占的字节会比RGB5

    2024年02月13日
    浏览(40)
  • 前端页面点击刷新-触发vue生命周期加载最新数据

    需求背景:layout布局,页面头部通过定时器获取后端消息的伪消息通知功能,在点击消息时获取所有消息总数并且刷新页面,以便触发vue的生命周期重新获取所有消息,消息展示在content中。  要触发页面刷新,可以使用vue路由的router.push方法,添加一个动态的query参数,可以

    2024年02月21日
    浏览(53)
  • JVM——类的生命周期(加载阶段,连接阶段,初始化阶段)

    类的生命周期 ⚫ 1、加载(Loading)阶段第一步是类加载器根据类的全限定名通过不同的渠道以二进制流的方式获取字节码信息。 程序员可以使用Java代码拓展的不同的渠道。 ⚫ 2、类加载器在加载完类之后,Java虚拟机会将字节码中的信息保存到方法区中。 ⚫ 3、类加载器在加载

    2024年02月05日
    浏览(50)
  • spring框架-概述(spring特性、生命周期)(一)

    Spring框架是一个开放源代码的J2EE应用程序框架,由Rod Johnson发起,是针对bean的生命周期进行管理的轻量级容器 ,是为了解决企业级编程开发中的复杂性,实现敏捷开发的应用型框架 IOC: (Inverse of Control ):一种思想 (容器帮我们创建对象并且管理和控制 ) 反转后不再由自己

    2024年02月10日
    浏览(38)
  • 小程序框架及小程序生命周期----超详细

    小程序开发框架的目标是通过尽可能简单、高效的方式让开发者可以在微信中开发具有原生 APP 体验的服务 整个小程序框架系统分为两部分:逻辑层(App Service)和 视图层(View)。小程序提供了自己的视图层描述语言 WXML 和 WXSS ,以及基于 JavaScript 的逻辑层框架,并在视图层

    2024年02月06日
    浏览(51)
  • 前端三大框架的生命周期最底层原理解析

    在现代前端开发中,React、Angular和Vue.js等三大框架已经成为了行业中最受欢迎和广泛使用的工具。这些框架的核心功能之一是生命周期管理,通过生命周期方法,我们可以在这些关键点执行特定的操作,以实现更好的控制和管理前端应用程序的行为。然而,你是否好奇这些生

    2024年02月13日
    浏览(54)
  • Android优化RecyclerView图片展示:Glide成堆加载批量Bitmap在RecyclerView成片绘制Canvas,Kotlin(b)

    对 Android GridLayoutManager Glide批量加载Bitmap绘制Canvas画在RecyclerView,Kotlin(a)-CSDN博客 改进,用Glide批量把Bitmap加载出来,然后在RecyclerView成片成堆的绘制Canvas,此种实现是RecyclerView加载多宫格图片展示,卡顿丢帧最低的一种实现,上下滑动流畅。 Android GridLayoutManager Glide批量

    2024年04月25日
    浏览(43)
  • Android Glide preload RecyclerView切入后台不可见再切换可见只加载当前视野可见区域item图片,Kotlin

    build.gradle文件: 如果手机图片很多,假设已经将全部图片装入宫格的列表,在快速上下滑动过程中,由于glide会累积每一个图片的加载任务,如果图片比较大,上下滑动时间又很长,那么累积任务会很严重,导致异常发生,实现在RecyclerView切入后台(或不可见)时候,然后再

    2024年02月10日
    浏览(48)
  • 【框架源码】Spring源码解析之Bean生命周期流程

    观看本文前,我们先思考一个问题,什么是Spring的bean的生命周期?这也是我们在面试的时候,面试官常问的一个问题。 在没有Spring之前,我们创建对象的时候,采用new的方式,当对象不在被使用的时候,由Java的垃圾回收机制回收。 而 Spring 中的对象是 bean,bean 和普通的 J

    2024年02月09日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包