1 Glide 使用 ---4.11.0
导入库
implementation 'com.github.bumptech.glide:glide:4.11.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
1.1 简单使用
class GlideTest : AppCompatActivity() {
lateinit var binding: ActivityGlideTestBinding
val imgUrl = "https://cn.bing.com/sa/simg/hpb/LaDigue_EN-CA1115245085_1920x1080.jpg"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_glide_test)
binding.showImg.setOnClickListener {
Glide.with(this).load(imgUrl).into(binding.contentImg)
}
}
}
1.2 其他部分用法
val doc1 = """
Glide 加载图片的方式
// 加载本地图片
File file = new File(getExternalCacheDir() + "/image.jpg");
Glide.with(this).load(file).into(imageView);
// 加载应用资源
int resource = R.drawable.image;
Glide.with(this).load(resource).into(imageView);
// 加载二进制流
byte[] image = getImageBytes();
Glide.with(this).load(image).into(imageView);
// 加载Uri对象
Uri imageUri = getImageUri();
Glide.with(this).load(imageUri).into(imageView);
"""
val doc2 = """
Glide 占位图,和一些属性实例
Glide.with(this)
.load(url)
.asBitmap()
.placeholder(R.drawable.loading)
.error(R.drawable.error)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);
Glide.with(this).load(url)
.asGif()
.placeholder(R.drawable.loading).error(R.drawable.error).diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);
Glide.with(this).load(url).placeholder(R.drawable.loading.error(R.drawable.error).diskCacheStrategy(DiskCacheStrategy.NONE)
.override(100, 100)
.into(imageView);
"""
2 三部曲with,load,into
2.1
第一步
Glide#width(xxxx) 目标获取 RequestManager
第二步
Glide#load(xxx) 目标获取 RequestBuilder
第三步
Glide#into(xxx) 获取和处理Target
- 运行队列,等待队列
- 活动缓存
- 内存缓存
- 网络模型
2.1.1 with
监听Activity/Fragment生命周期
当我们的Fragment或Activity不可见的时候暂停请求,当我们的Fragment或Activity可见的时候回复请求
处理前台可见的 Activity / Fragment,提高资源利用率;
在有必要时释放资源以避免在应用在后台时被杀死,提高稳定性;
Glide#with(params)
with会有很多重载方法,params参数有这些种类:(FragmentActivity,androidx.fragment.app.Fragment,android.app.Fragment,View)
通过获取RequestManagerRetriever 进行检索
RequestManagerRetriever#get方法
多个重载
通过源码,我们会看到四个重载方法
public RequestManager get(@NonNull Context context)
public RequestManager get(@NonNull FragmentActivity activity)
public RequestManager get(@NonNull Fragment fragment)
public RequestManager get(@NonNull Activity activity)
public RequestManager get(@NonNull View view)
通过这些发放的分析,我们得出下面的分析
生命周期的作用域(1.Application, 2.Activity, 3.Fragment)
with 参数 | 作用域 | 代码中线程 |
---|---|---|
Application | 子线程使用with | |
View | Fragment/Activity | 主线程 |
Fragment | Fragment | 主线程 |
Activity | Activity | 主线程 |
FragmentActivity | Activity | 主线程 |
ServiceContext/ApplicationContext | Application | 主线程 |
一共分为两种:
第一种是作用域Application,它的生命周期是全局 的,不搞空白Fragment绑定Activity/Fragment
第二种是作用域非Application,它的生命周期是,专门搞空白Fragment绑定 Activity/Fragment
生成默认隐藏fragment ,我们发现有着几个方法
private RequestManager supportFragmentGet(
@NonNull Context context,
@NonNull FragmentManager fm,
@Nullable Fragment parentHint,
boolean isParentVisible)
private RequestManager fragmentGet(
@NonNull Context context,
@NonNull android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible)
supportFragmentGet---->getSupportRequestManagerFragment
获取SupportRequestManagerFragment (Tag:FRAGMENT_TAG)的fragment
private SupportRequestManagerFragment getSupportRequestManagerFragment(
@NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
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;
}
fragmentGet---->getRequestManagerFragment
获取RequestManagerFragment (Tag:FRAGMENT_TAG)的fragment
private RequestManagerFragment getRequestManagerFragment(
@NonNull final android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
current = pendingRequestManagerFragments.get(fm);
if (current == null) {
current = new RequestManagerFragment();
current.setParentFragmentHint(parentHint);
if (isParentVisible) {
current.getGlideLifecycle().onStart();
}
pendingRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
生命周期的绑定
【记录保存】 FragmentManager -SupportRequestManagerFragment
RequestManagerRetriever .java
final Map
new HashMap<>();
supportFragmentGet----getSupportRequestManagerFragment
- 从FragmentManager中获取SupportRequestManagerFragment
SupportRequestManagerFragment current =
getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
2.从该 Fragment 中获取 RequestManager
RequestManager requestManager =current.getRequestManager();
3.首次获取,则实例化 RequestManager
------> getSupportRequestManagerFragment
1.1 尝试获取 FRAGMENT_TAG 对应的 Fragment
1.2 尝试从临时记录中获取Fragment
如果为获取到
1.3 current==null---实例化 Fragment
1.3.1 创建对象SupportRequestManagerFragment
1.3.2 如果父层可见,则调用 onStart() 生命周期
1.3.3 临时记录映射关系pendingSupportRequestManagerFragments.put(fm, current)
1.3.4 提交 Fragment 事务
1.3.5 post 一个消息
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
-》post 一个消息分析: RequestManagerRetriever 本身实现了Handler的callback
handleMessage中
case ID_REMOVE_SUPPORT_FRAGMENT_MANAGER:
FragmentManager supportFm = (FragmentManager) message.obj;
key = supportFm;
removed = pendingSupportRequestManagerFragments.remove(supportFm);
break;
就是为了避免 SupportRequestManagerFragment 在一个作用域中重复创建。
因为 commitAllowingStateLoss() 是将事务 post 到消息队列中的,也就是说,事 务是异步处理的,而不是同步处理的。假设没有临时保存记录,一旦在事务异步等待 执行时调用了 Glide.with(...) ,就会在该作用域中重复创建 Fragment。
生命周期的监听机制
Glide内部会在 Activity/Fragment生命周期监听,网络变化监听,自动取消加 载或者重新加载
框架为每个Activity 和 Fragment 作用域创建了 一个无UI的Fragment
分析这个空Fragment---》 SupportRequestManagerFragment.java
看下我们比较关心的代码
ActivityFragmentLifecycle lifecycle
public SupportRequestManagerFragment() {
this(new ActivityFragmentLifecycle());
}
public SupportRequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
this.lifecycle = lifecycle;
}
public void setRequestManager(@Nullable RequestManager requestManager) {
this.requestManager = requestManager;
}
@Override
public void onStart() {
super.onStart();
lifecycle.onStart();
}
@Override
public void onStop() {
super.onStop();
lifecycle.onStop();
}
@Override
public void onDestroy() {
super.onDestroy();
lifecycle.onDestroy();
unregisterFragmentWithRoot();
}
回溯一下,RequestManagerRetriever.java 和 RequestManager.java
- 实例化RequestManager
Glide glide = Glide.get(context);
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
- RequestManager 工厂
public interface RequestManagerFactory {
@NonNull
RequestManager build(
@NonNull Glide glide,
@NonNull Lifecycle lifecycle,
@NonNull RequestManagerTreeNode requestManagerTreeNode,
@NonNull Context context);
}
- 默认工厂接口实现
private static final RequestManagerFactory DEFAULT_FACTORY =
new RequestManagerFactory() {
@NonNull
@Override
public RequestManager build(
@NonNull Glide glide,
@NonNull Lifecycle lifecycle,
@NonNull RequestManagerTreeNode requestManagerTreeNode,
@NonNull Context context) {
return new RequestManager(glide, lifecycle, requestManagerTreeNode, context);
}
};
RequestManager.java 源码我们关心的部分
final Lifecycle lifecycle;
public RequestManager(
@NonNull Glide glide,
@NonNull Lifecycle lifecycle,
@NonNull RequestManagerTreeNode treeNode,
@NonNull Context context) {
......
this.lifecycle = lifecycle;
this.requestTracker = requestTracker;// 生命周期回调
。。。
if (Util.isOnBackgroundThread()) {
mainHandler.post(addSelfToLifecycle);
} else {// 添加监听
lifecycle.addListener(this);
}
。。。
public synchronized void onDestroy() {
targetTracker.onDestroy();
......
lifecycle.removeListener(this);//remove 监听
}
}
实例化 RequestManager 时需要一个 Lifecycle对象,这个对象是 在无界面 Fragment 中创建的,当 Fragment 的生命周期变化时,就是通过这个 Lifecycle 对象将事件分发到RequestManager
生命周期的回调
RequestsManger 收到的回调ConnectivityMonitor
public interface LifecycleListener {
void onStart();
void onStop();
void onDestroy();
}
Activity/Fragment 不可见时暂停请求 (onStop() ) 函数 Activity/Fragment 可见时恢复请求 (onStart() ) 函数 Activity/Fragment 销毁时销毁请求 (onDestroy() )函数
---》 RequestManger 操作 requestTracker
@Override
public synchronized void onStop() {
pauseRequests();
targetTracker.onStop();
}
@Override
public synchronized void onStart() {
resumeRequests();
targetTracker.onStart();
}
public synchronized void resumeRequests() {
requestTracker.resumeRequests();
}
public synchronized void pauseRequests() {
requestTracker.pauseRequests();
}
@Override
public synchronized void onDestroy() {
targetTracker.onDestroy();
for (Target> target : targetTracker.getAll()) {
clear(target);
}
targetTracker.clear();
requestTracker.clearRequests();
lifecycle.removeListener(this);
lifecycle.removeListener(connectivityMonitor);
mainHandler.removeCallbacks(addSelfToLifecycle);
glide.unregisterRequestManager(this);
}