Android-Glide详解

server/2024/12/18 22:49:56/

目录

一,介绍

二,使用

三,源码分析思路

四,with源码分析

五,模拟Glide生命周期管理


一,介绍

Glide目前是安卓最主流的加载图片的框架,也是源码最为复杂的框架之一。 要想完完全全吃透Glide的源码,可能需要半年甚至更多的时间。

但是如果分析过Glide的源码,不仅对我们的架构能力有很大提高,也会对面试中的关于Glide的问题知其然更知其所以然。

Glide的精髓,在于它的生命周期的管理和缓存策略

二,使用

Glide的使用及其简单

 // 项目的build.gradle添加依赖implementation 'com.github.bumptech.glide:glide:4.11.0'annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'

在清单文件添加网络权限:

 <uses-permission android:name="android.permission.INTERNET"/>

布局文件很简单就一个imageview:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><ImageViewandroid:id="@+id/iv"android:layout_width="match_parent"android:layout_height="match_parent"/></androidx.constraintlayout.widget.ConstraintLayout>

使用:

class MainActivity : AppCompatActivity() {//图片urlprivate val url ="https://q7.itc.cn/q_70/images03/20240714/93ce0113753a4ff4b5f4e48f27ed3739.jpeg"override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val iv =findViewById<ImageView>(R.id.iv)Glide.with(this).load(url).into(iv)}
}

效果:

三,源码分析思路

Glide的源码分析,我们可以从使用角度,拆分为三部分去分析。

class MainActivity : AppCompatActivity() {//图片urlprivate val url ="https://q7.itc.cn/q_70/images03/20240714/93ce0113753a4ff4b5f4e48f27ed3739.jpeg"override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val iv =findViewById<ImageView>(R.id.iv)//第一步 调用with  得到RequestManagerval requestManager:RequestManager = Glide.with(this)//第二步 RequestManager调用load 得到requestBuliderval requestBulider:RequestBuilder<Drawable> =requestManager.load(url)//第三步 requestBulider调用intorequestBulider.into(iv)}
}

这样拆分的话,思路会比较清晰。

四,with源码分析

首先我们看一下with的源码:

@NonNull
public static RequestManager with(@NonNull Context context) {return getRetriever(context).get(context);
}@NonNull
public static RequestManager with(@NonNull Activity activity) {return getRetriever(activity).get(activity);
}@NonNull
public static RequestManager with(@NonNull FragmentActivity activity) {return getRetriever(activity).get(activity);
}@NonNull
public static RequestManager with(@NonNull Fragment fragment) {return getRetriever(fragment.getContext()).get(fragment);
}@SuppressWarnings("deprecation")
@Deprecated
@NonNull
public static RequestManager with(@NonNull android.app.Fragment fragment) {return getRetriever(fragment.getActivity()).get(fragment);
}@NonNull
public static RequestManager with(@NonNull View view) {return getRetriever(view.getContext()).get(view);
}

它可以接受的参数类型很多,确保多种场景下的使用

然后继续往下看getRetriever这个函数:

@NonNull
private static RequestManagerRetriever getRetriever(@Nullable Context context) {// Context could be null for other reasons (ie the user passes in null), but in practice it will// only occur due to errors with the Fragment lifecycle.Preconditions.checkNotNull(context,"You cannot start a load on a not yet attached View or a Fragment where getActivity() "+ "returns null (which usually occurs when getActivity() is called before the Fragment "+ "is attached or after the Fragment is destroyed).");return Glide.get(context).getRequestManagerRetriever();
}

判空不用看,直接看get(context)这个函数:

@NonNull
public static Glide get(@NonNull Context context) {if (glide == null) {GeneratedAppGlideModule annotationGeneratedModule =getAnnotationGeneratedGlideModules(context.getApplicationContext());synchronized (Glide.class) {if (glide == null) {checkAndInitializeGlide(context, annotationGeneratedModule);}}}return glide;
}

这个就是我们熟悉的双重检测单例模式,不了解的可以参考文章:Android 设计模式--单例模式_android开发饿汉单例-CSDN博客

然后我们看看 checkAndInitializeGlide(context, annotationGeneratedModule):

@GuardedBy("Glide.class")
private static void checkAndInitializeGlide(@NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) {// In the thread running initGlide(), one or more classes may call Glide.get(context).// Without this check, those calls could trigger infinite recursion.if (isInitializing) {throw new IllegalStateException("You cannot call Glide.get() in registerComponents(),"+ " use the provided Glide instance instead");}isInitializing = true;initializeGlide(context, generatedAppGlideModule);isInitializing = false;
}

这里好像没有什么具体的信息,我们接着往下看initializeGlide(context,generatedAppGlideModule)这个函数:

@GuardedBy("Glide.class")
private static void initializeGlide(@NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) {initializeGlide(context, new GlideBuilder(), generatedAppGlideModule);
}

好的,依然继续往下看initializeGlide(context, new GlideBuilder(), generatedAppGlideModule)

@GuardedBy("Glide.class")
@SuppressWarnings("deprecation")
private static void initializeGlide(@NonNull Context context,@NonNull GlideBuilder builder,@Nullable GeneratedAppGlideModule annotationGeneratedModule) {//获取应用级别的上下文Context applicationContext = context.getApplicationContext();List<com.bumptech.glide.module.GlideModule> manifestModules = Collections.emptyList();if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {manifestModules = new ManifestParser(applicationContext).parse();}if (annotationGeneratedModule != null&& !annotationGeneratedModule.getExcludedModuleClasses().isEmpty()) {Set<Class<?>> excludedModuleClasses = annotationGeneratedModule.getExcludedModuleClasses();Iterator<com.bumptech.glide.module.GlideModule> iterator = manifestModules.iterator();while (iterator.hasNext()) {com.bumptech.glide.module.GlideModule current = iterator.next();if (!excludedModuleClasses.contains(current.getClass())) {continue;}if (Log.isLoggable(TAG, Log.DEBUG)) {Log.d(TAG, "AppGlideModule excludes manifest GlideModule: " + current);}iterator.remove();}}if (Log.isLoggable(TAG, Log.DEBUG)) {for (com.bumptech.glide.module.GlideModule glideModule : manifestModules) {Log.d(TAG, "Discovered GlideModule from manifest: " + glideModule.getClass());}}
//通过注解生成的代码拿到 RequestManagerFactoryRequestManagerRetriever.RequestManagerFactory factory =annotationGeneratedModule != null? annotationGeneratedModule.getRequestManagerFactory(): null;
//将拿到的工厂添加到 GlideBuilderbuilder.setRequestManagerFactory(factory);for (com.bumptech.glide.module.GlideModule module : manifestModules) {module.applyOptions(applicationContext, builder);}if (annotationGeneratedModule != null) {annotationGeneratedModule.applyOptions(applicationContext, builder);}
//通过 Builder 建造者模式,构建出 Glide 实例对象Glide glide = builder.build(applicationContext);
//注册组件回调for (com.bumptech.glide.module.GlideModule module : manifestModules) {try {module.registerComponents(applicationContext, glide, glide.registry);} catch (AbstractMethodError e) {throw new IllegalStateException("Attempting to register a Glide v3 module. If you see this, you or one of your"+ " dependencies may be including Glide v3 even though you're using Glide v4."+ " You'll need to find and remove (or update) the offending dependency."+ " The v3 module name is: "+ module.getClass().getName(),e);}}if (annotationGeneratedModule != null) {annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);}applicationContext.registerComponentCallbacks(glide);
//将构建出来的 glide 赋值给 Glide 的静态变量Glide.glide = glide;
}

这个函数里面的信息量是非常大的,主要是进行了一系列的初始化操作,通过 Builder 建造者模式,构建出 Glide 实例对象,接着我们看看builder模式进行了哪些构建:

@NonNull
Glide build(@NonNull Context context) {
//网络请求的线程池if (sourceExecutor == null) {sourceExecutor = GlideExecutor.newSourceExecutor();}
//本地磁盘缓存的线程池if (diskCacheExecutor == null) {diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();}
//加载图片动画的一个线程池if (animationExecutor == null) {animationExecutor = GlideExecutor.newAnimationExecutor();}
//对图片加载到内存的一个计算if (memorySizeCalculator == null) {memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();}
//默认网络连接监控的工厂if (connectivityMonitorFactory == null) {connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();}
//Bitmap 对象池if (bitmapPool == null) {int size = memorySizeCalculator.getBitmapPoolSize();if (size > 0) {bitmapPool = new LruBitmapPool(size);} else {bitmapPool = new BitmapPoolAdapter();}}
//数组对象池if (arrayPool == null) {arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());}
//资源内存缓存if (memoryCache == null) {memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());}
//磁盘缓存的工厂if (diskCacheFactory == null) {diskCacheFactory = new InternalCacheDiskCacheFactory(context);}
//构建执行缓存策略跟线程池的引擎if (engine == null) {engine =new Engine(memoryCache,diskCacheFactory,diskCacheExecutor,sourceExecutor,GlideExecutor.newUnlimitedSourceExecutor(),animationExecutor,isActiveResourceRetentionAllowed);}if (defaultRequestListeners == null) {defaultRequestListeners = Collections.emptyList();} else {defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);}
//RequestManagerRetriever 请求管理类RequestManagerRetriever requestManagerRetriever =new RequestManagerRetriever(requestManagerFactory);return new Glide(context,engine,memoryCache,bitmapPool,arrayPool,requestManagerRetriever,connectivityMonitorFactory,logLevel,defaultRequestOptionsFactory,defaultTransitionOptions,defaultRequestListeners,isLoggingRequestOriginsEnabled,isImageDecoderEnabledForBitmaps);
}

这里就完成了Glide的构建。

然后我们回到最开始的getRetriever(activity).get(activity),看看这个函数里面都干了些什么:

@NonNull
public RequestManager get(@NonNull FragmentActivity activity) {
//首先判断当前是否在子线程中if (Util.isOnBackgroundThread()) {
//在子线程中 就通过Application级别的上下文加载return get(activity.getApplicationContext());} else {
//检查Activity是否已经销毁assertNotDestroyed(activity);
//拿到当前activity的fragmentmanagerFragmentManager fm = activity.getSupportFragmentManager();
//生成一个fragment 然后绑定一个请求管理类RequestManagerreturn supportFragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));}
}

看到这里,我们就应该意识到一个问题,如果我们在子线程中去调用Glide的话,就会使用应用级别的上下文去加载图片,这样大量使用,可能会导致内存泄漏。

然后在主线程中使用,就是Glide的精髓之一了,加载一个透明fragment来感应当前页面的生命周期的变化。

接着看看supportFragmentGet是怎么实现的:

@NonNull
private RequestManager supportFragmentGet(@NonNull Context context,@NonNull FragmentManager fm,@Nullable Fragment parentHint,boolean isParentVisible) {
//在当前的 Acitivty 添加一个 Fragment 用于管理请求的生命周期SupportRequestManagerFragment current =getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
//拿到当前请求的管理类RequestManager requestManager = current.getRequestManager();
//如果为空 就创建一个if (requestManager == null) {// TODO(b/27524013): Factor out this Glide.get() call.Glide glide = Glide.get(context);requestManager =factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);current.setRequestManager(requestManager);}return requestManager;
}

这里就是添加一个fragment管理生命周期。然后返回一个RequestManager对象。

接下来再具体看看getSupportRequestManagerFragment是怎么添加的:

@NonNull
private SupportRequestManagerFragment getSupportRequestManagerFragment(@NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
//通过tag拿到fragment实例 避免重复SupportRequestManagerFragment current =(SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
//没有实例的话 就去缓存找if (current == null) {current = pendingSupportRequestManagerFragments.get(fm);
//缓存也没有 就创建一个if (current == null) {current = new SupportRequestManagerFragment();current.setParentFragmentHint(parentHint);if (isParentVisible) {current.getGlideLifecycle().onStart();}pendingSupportRequestManagerFragments.put(fm, current);fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();}}return current;
}

这里主要是拿到fragment实例。

从上面我们可以看出Glide主要是做了一些初始化的工作,缓存,线程池,复用池的构建等等。

然后绑定了一个fragment来管理生命周期

with的源码差不多就是这些,可能比较繁琐,但是不像rxjava那样绕来绕去的,主线还是比较清晰的。

五,模拟Glide生命周期管理

首先创建一个接口,监听生命周期回调:

public interface LifecycleListener {void onCreate();void onStart();void onStop();void onDestroy();}

然后创建一个用来管理生命周期监听的接口:

public interface Lifecycle {void addListener(@NonNull LifecycleListener listener);void removeListener(@NonNull LifecycleListener listener);}

通过上面的分析,我们知道Glide传入的上下文有应用级别的和非应用级别的。所以我们首先创建一个应用级别的Lifecycle:

public class ApplicationLifecycle implements Lifecycle {@Overridepublic void addListener(@NonNull LifecycleListener listener) {/*** APP启动的时候,执行onCreate*/listener.onCreate();}@Overridepublic void removeListener(@NonNull LifecycleListener listener) {//APP销毁的时候,啥也不用做了}
}

然后创建一个非应用级别的lifecycle:

public class ActivityFragmentLifecycle implements Lifecycle {private final Set<LifecycleListener> lifecycleListeners =Collections.newSetFromMap(new WeakHashMap<LifecycleListener, Boolean>());private boolean isStarted; private boolean isDestroyed; @Overridepublic void addListener(@NonNull LifecycleListener listener) {lifecycleListeners.add(listener);if (isDestroyed) {listener.onDestroy();} else if (isStarted) {listener.onCreate();} else {listener.onStop();  }}@Overridepublic void removeListener(@NonNull LifecycleListener listener) {lifecycleListeners.remove(listener);}void onStart() {isStarted = true;for (LifecycleListener lifecycleListener : lifecycleListeners) {lifecycleListener.onCreate();}}void onStop() {isStarted = false;for (LifecycleListener lifecycleListener : lifecycleListeners) {lifecycleListener.onStop();}}void onDestroy() {isDestroyed = true;for (LifecycleListener lifecycleListener : lifecycleListeners) {lifecycleListener.onDestroy();}}
}

创建一个具体的RequestManager 管理生命周期:

public class RequestManager implements LifecycleListener {private Lifecycle lifecycle;public RequestManager(Lifecycle lifecycle, Context applicationContext) {this.lifecycle = lifecycle;this.lifecycle.addListener(this);}@Overridepublic void onCreate() {Log.d(LOG.TAG, "yh-----onCreate");}@Overridepublic void onStart() {Log.d(LOG.TAG, "yh-----onStart");}@Overridepublic void onStop() {Log.d(LOG.TAG, "yh-----onStop");}@Overridepublic void onDestroy() {Log.d(LOG.TAG, "yh-----onDestroy");this.lifecycle.removeListener(this);}
}

创建一个空白的fragment:

public class RequestManagerFragment extends Fragment {private final ActivityFragmentLifecycle lifecycle;@Nullableprivate RequestManager requestManager;public RequestManagerFragment() {this(new ActivityFragmentLifecycle());}@VisibleForTesting@SuppressLint("ValidFragment")public RequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {this.lifecycle = lifecycle;}public void setRequestManager(@Nullable RequestManager requestManager) {this.requestManager = requestManager;}@NonNullpublic ActivityFragmentLifecycle getGlideLifecycle() {return lifecycle;}@Overridepublic void onAttach(@NonNull Context context) {super.onAttach(context);this.lifecycle.addListener(requestManager);}@Nullablepublic RequestManager getRequestManager() {return requestManager;}@Overridepublic void onDetach() {super.onDetach();}@Overridepublic void onStart() {super.onStart();lifecycle.onStart();}@Overridepublic void onStop() {super.onStop();lifecycle.onStop();}@Overridepublic void onDestroy() {super.onDestroy();lifecycle.onDestroy();}
}

简单写一个Glide管理类:

public class Glide {private static volatile Glide glide;@NonNullpublic static Glide get(@NonNull Context context) {if (glide == null) {synchronized (Glide.class) {if (glide == null) {glide = new Glide();}}}return glide;}@NonNullpublic static RequestManager with(@NonNull Context context) {return new RequestManager(new ActivityFragmentLifecycle(),context);}@NonNullpublic static RequestManager withApplication(@NonNull Context context) {return new RequestManager(new ApplicationLifecycle(),context);}}

使用也很简单:

public class DemoActivity extends AppCompatActivity {@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Glide.with(this);Glide.withApplication(this.getApplicationContext());}
}

这样当DemoActivity创建时,会创建一个ActivityFragmentLifecycle,执行它的onStart方法,从而调用RequestManager的onStart方法,onDestory也是同样的道理。这样就实现了生命周期的检测。这里只是简单写下有助于理解Glide内部是怎么做的。

关于load和into以及缓存机制 改天再写。


http://www.ppmy.cn/server/151280.html

相关文章

小程序开发常见问题

一、开发方案选择 1.小程序原生开发&#xff1a;需要live-player组件资质&#xff0c;对开发者的资质要求较高&#xff0c;开发难度较大&#xff1b; 2.小程序内嵌H5&#xff1a;因校验文档上限&#xff0c;目前平台已经不支持配置校验文件&#xff1b; 3.半屏小程序&#xff1…

Excel中如何消除“长短款”

函数微调可以可以实施&#xff0c;简单且易于操作的气球&#x1f388;涨缩更妙。 (笔记模板由python脚本于2024年12月17日 06:19:13创建&#xff0c;本篇笔记适合用Excel操作数据的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Fre…

Python Flask Web框架快速入门

Flask 入门Demo Flask 开发环境搭建&#xff0c;执行如下指令&#xff1a; pip install flask# 第一节: Flask 快速入门from flask import Flask app Flask(__name__)app.route(/flask) def hello_flask():return Hello Flaskapp.run()核心代码剖析&#xff1a; 从flask包导…

如何利用PHP和phpSpider爬取电子商务网站的产品价格

利用PHP和phpSpider爬取电子商务网站的产品价格涉及多个步骤&#xff0c;包括环境准备、爬虫配置、数据解析和存储等。以下是一个简要的指南&#xff1a; 一、环境准备 安装PHP&#xff1a;确保你的系统上已经安装了PHP&#xff0c;并且可以通过命令行访问。安装Composer&…

css中样式前加 css样式前面加个圆点

创建CSS样式,样式名称的前面需要加什么 1、我们只知道符号代表的意思是at&#xff0c;其翻译是 在... 例如media就是 在媒介上。没人规定本身具有什么意义&#xff0c;或者说就算规定了我们也改变不了&#xff0c;只需要知道其规定属性的用法即可。 2、px;}然后根据你自己索要…

SQL 语句在 MySQL 中的执行过程

SQL 语句在 MySQL 中的执行过程 在数据库管理系统中&#xff0c;理解 SQL 语句的执行过程对于优化查询、提高性能以及解决问题至关重要。本文将深入探讨 SQL 语句在 MySQL 中的执行过程&#xff0c;为读者提供全面的了解。 一、MySQL 架构概述 MySQL 主要由以下几个部分组成&a…

[ZMQ] -- ZMQ通信收发多个Proto数据结构 2

为了在 ZeroMQ 的一帧数据中发送两个不同的主题&#xff08;topic&#xff09;&#xff0c;并且每个主题包含不同的 Protobuf 消息&#xff0c;可以使用多部分消息的功能。具体来说&#xff0c;将发送一个包含四部分的消息&#xff1a; 第一个主题&#xff08;topic1&#xff…

使用pygame做游戏(2):2048游戏的进一步改造,以失败告终

前言 受《Python树莓派编程从零开始》里的示例启发&#xff0c;我决定将上篇的2048游戏进行“面向对象化”改造。 这次除了要建立一些对象&#xff0c;还要能有移动效果&#xff0c;并能显示中文。 另外我还发现一个bug&#xff1a;方块放满了不代表输了&#xff0c;还要检查能…