二.Glide使用的几个设计模式:
1、 单例模式
a) 饿汉式(静态常量)
优点:这种写法比较简单,就是在类装载的时候就完成实例化。避免了线程同步问题。
缺点:在类装载的时候就完成实例化,没有达到Lazy Loading的效果。如果从始至终从未使用过这个实例,则会造成内存的浪费。
b) 饿汉式(静态代码块)
同上
c) 懒汉式(线程不安全)
d) 懒汉式(线程安全,同步方法)
缺点:效率低。
e) 懒汉式(同步代码块)
缺点:线程不安全
f) 双重检查
g) 静态内部类
静态内部类方式在Singleton类被装载时并不会立即实例化,而是在需要实例化时,调用getInstance方法,才会装载SingletonInstance类,从而完成Singleton的实例化。
类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。
优点:避免了线程不安全,延迟加载,效率高。
h) 枚举
线程安全,防止序列化反射攻击
2、 空对象模式
https://blog.csdn.net/qq_16498553/article/details/106821947?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_title~default-0-106821947-blog-106281772.pc_relevant_multi_platform_whitelistv2&spm=1001.2101.3001.4242.1&utm_relevant_index=3
package com.funshion.player;
public class User {
String id;
String name;
String password;
String phone;
private User(Builder builder) {
id = builder.id;
name = builder.name;
password = builder.password;
phone = builder.phone;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public String getPassword() {
return password;
}
public String getPhone() {
return phone;
}
@Override
public String toString() {
return "User{" +
"id='" + id + ''' +
", name='" + name + ''' +
", password='" + password + ''' +
", phone='" + phone + ''' +
'}';
}
public static final class Builder {
private String id;
private String name;
private String password;
private String phone;
public Builder() {
}
public Builder id(String val) {
id = val;
return this;
}
public Builder name(String val) {
name = val;
return this;
}
public Builder password(String val) {
password = val;
return this;
}
public Builder phone(String val) {
phone = val;
return this;
}
public User build() {
return new User(this);
}
}
}
package com.funshion.player;
public class Test {
public static void main(String[] args) {
User user=new User.Builder().id(“1”).name(“张三”).password(“123456”)
.phone(“15820638007”).build();
System.out.println(user.toString());
}
}
Glide 加载原理
Glide.with(context)
GeneratedAppGlideModuleImpl
AppGlideModule
LibraryGlideModule
applicationContext.registerComponentCallbacks(glide);
1:Activity在接收到Configuration变化时会销毁重建 调用此方法
2:内存不够了,如果没专门指定触发时机,那它会发生在所有的后台进程都被干掉的时候(在service和前台UI被干掉之前);这个方法结束后系统会触发GC。
sourceExecutor
源线程池
diskCacheExecutor
磁盘缓存线程池
animationExecutor
动画线程池
MemorySizeCalculator
动态计算内存缓存大小
arrayPoolSize =
isLowMemoryDevice(builder.activityManager)
? builder.arrayPoolSizeBytes / LOW_MEMORY_BYTE_ARRAY_POOL_DIVISOR
: builder.arrayPoolSizeBytes;
//其中会先获取当前进程可使用内存大小,
//然后通过判断是否是否为低内存设备乘以相应的系数,
//普通设备是乘以 0.4,低内存为 0.33,这样得到的是 Glide 可使用的最大内存阈值 maxSize
int maxSize =
getMaxSize(
builder.activityManager, builder.maxSizeMultiplier, builder.lowMemoryMaxSizeMultiplier);
int widthPixels = builder.screenDimensions.getWidthPixels();
int heightPixels = builder.screenDimensions.getHeightPixels();
//计算一张格式为 ARGB_8888 ,大小为屏幕大小的图片的占用内存大小
//BYTES_PER_ARGB_8888_PIXEL 值为 4
int screenSize = widthPixels * heightPixels * BYTES_PER_ARGB_8888_PIXEL;
int targetBitmapPoolSize = Math.round(screenSize * builder.bitmapPoolScreens);
int targetMemoryCacheSize = Math.round(screenSize * builder.memoryCacheScreens);
//去掉 ArrayPool 占用的内存后还剩余的内存
int availableSize = maxSize - arrayPoolSize;
if (targetMemoryCacheSize + targetBitmapPoolSize <= availableSize) {
//未超出内存限制
memoryCacheSize = targetMemoryCacheSize;
bitmapPoolSize = targetBitmapPoolSize;
} else {
//超出内存限制
float part = availableSize / (builder.bitmapPoolScreens + builder.memoryCacheScreens);
memoryCacheSize = Math.round(part * builder.memoryCacheScreens);
bitmapPoolSize = Math.round(part * builder.bitmapPoolScreens);
}
bitmapPool
bitmap池 复用 Bitmap 从而避免重复创建 Bitmap 而带来的内存浪费
arrayPool
把输入流转化为文件时,需要创建一个新的字节数组,如果不用 ArrayPool,而图片是在列表中加载的,那就会创建很多不必要的的字节数组。
memoryCache
内存缓存
diskCacheFactory
磁盘缓存
Registry:
ModelLoaderRegistry
数据加载器登记处 加载数据
EncoderRegistry
编码器登记处 提供将数据持久化存储到磁盘文件中的功能
ResourceDecoderRegistry
资源解码器登记处 能够将各种类型数据,例如文件、byte数组等数据解码成bitmap或者drawable等资源
ResourceEncoderRegistry
资源编码器登记处 提供将bitmap或者drawable等资源文件进行持久化存储的功能
DataRewinderRegistry
数据重定向登记处 重定向ByteBuffer中的position或者stream中的指针位置等
TranscoderRegistry
转码器登记处 提供将不同资源类型进行转换的能力,例如将bitmap转成drawable等
ImageHeaderParserRegistry
图片头部信息解析器登记处
可以在 AppGlideModule 的 registerComponents() 方法中获取到 registry 实例,通过这个实例就可以替换掉对应的实现。
RequestManager
管理生命周期
// 代码略...
private final ActivityFragmentLifecycle lifecycle;
// 代码略...
@Override
public void onStart() {
super.onStart();
lifecycle.onStart();
}
@Override
public void onStop() {
super.onStop();
lifecycle.onStop();
}
@Override
public void onDestroy() {
super.onDestroy();
lifecycle.onDestroy();
}
// 代码略...
}
RequestManager implements LifecycleListener
DefaultConnectivityMonitor
网络变化
Glide.with(imageView.getContext()).load(url)
RequestBuilder
Glide.with(imageView.getContext()).load(url).into()
ImageViewTargetFactory
将imageVIew转换为target
buildRequestRecursive()
创建request
buildThumbnailRequestRecursive()
创建缩略图请求,无论如何都会创建这个
Engine 引擎
所有图片加载渠道公用,管理Jobs,load()方法,EngineJob,DecodeJob工厂创建
活动缓存 -》内存缓存-》磁盘缓存/网络加载
EngineJob.start
根据是否从缓存中加载、是否使用无限制大小线程池、是否使用动画线程池等条件得到相应的线程池
//执行原因,第一次执行,值为INITIALIZE
switch (runReason) {
case INITIALIZE:
stage = getNextStage(Stage.INITIALIZE);
currentGenerator = getNextGenerator();
runGenerators();
break;
case SWITCH_TO_SOURCE_SERVICE:
runGenerators();
break;
case DECODE_DATA:
decodeFromRetrievedData();
break;
default:
throw new IllegalStateException("Unrecognized run reason: " + runReason);
}
}
//首先明确几种装状态有利于阅读
//RESOURCE_CACHE:原始数据经过转换处理过的数据;
//DATA_CACHE:从服务端获取的原始数据;
//SOURCE:发送网络请求获取数据
switch (current) {
case INITIALIZE:
//根据磁盘缓存策略,判断使用原始数据缓存,还是使用转换处理过的缓存数据。
return diskCacheStrategy.decodeCachedResource()
? Stage.RESOURCE_CACHE
: getNextStage(Stage.RESOURCE_CACHE);
case RESOURCE_CACHE:
//根据缓存策略,判断是否使用原始文件缓存。
return diskCacheStrategy.decodeCachedData()
? Stage.DATA_CACHE
: getNextStage(Stage.DATA_CACHE);
case DATA_CACHE:
// Skip loading from source if the user opted to only retrieve the resource from cache.
//如果是只是用缓存,那么就返回FINISH,否则返回SOURCE
return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
case SOURCE:
case FINISHED:
return Stage.FINISHED;
default:
throw new IllegalArgumentException("Unrecognized stage: " + current);
}
}
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);
}
}
/默认的策略是DiskCacheStrategy.AUTOMATIC
DiskCacheStrategy有五个常量:
DiskCacheStrategy.ALL 使用DATA和RESOURCE缓存远程数据,仅使用RESOURCE来缓存本地数据。
DiskCacheStrategy.NONE 不使用磁盘缓存
DiskCacheStrategy.DATA 在资源解码前就将原始数据写入磁盘缓存
DiskCacheStrategy.RESOURCE 在资源解码后将数据写入磁盘缓存,即经过缩放等转换后的图片资源。
DiskCacheStrategy.AUTOMATIC 根据原始图片数据和资源编码策略来自动选择磁盘缓存策略。/



