1 Glide 使用 ---4.11.0
導(dǎo)入庫(kù)
implementation 'com.github.bumptech.glide:glide:4.11.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
1.1 簡(jiǎn)單使用
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);
// 加載應(yīng)用資源
int resource = R.drawable.image;
Glide.with(this).load(resource).into(imageView);
// 加載二進(jìn)制流
byte[] image = getImageBytes();
Glide.with(this).load(image).into(imageView);
// 加載Uri對(duì)象
Uri imageUri = getImageUri();
Glide.with(this).load(imageUri).into(imageView);
"""
val doc2 = """
Glide 占位圖,和一些屬性實(shí)例
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) 目標(biāo)獲取 RequestManager
第二步
Glide#load(xxx) 目標(biāo)獲取 RequestBuilder
第三步
Glide#into(xxx) 獲取和處理Target
- 運(yùn)行隊(duì)列暖眼,等待隊(duì)列
- 活動(dòng)緩存
- 內(nèi)存緩存
- 網(wǎng)絡(luò)模型
2.1.1 with
監(jiān)聽(tīng)Activity/Fragment生命周期
當(dāng)我們的Fragment或Activity不可見(jiàn)的時(shí)候暫停請(qǐng)求,當(dāng)我們的Fragment或Activity可見(jiàn)的時(shí)候回復(fù)請(qǐng)求
處理前臺(tái)可見(jiàn)的 Activity / Fragment纺裁,提高資源利用率;
在有必要時(shí)釋放資源以避免在應(yīng)用在后臺(tái)時(shí)被殺死诫肠,提高穩(wěn)定性;
Glide#with(params)
with會(huì)有很多重載方法,params參數(shù)有這些種類:(FragmentActivity欺缘,androidx.fragment.app.Fragment栋豫,android.app.Fragment,View)
通過(guò)獲取RequestManagerRetriever 進(jìn)行檢索
RequestManagerRetriever#get方法
多個(gè)重載
通過(guò)源碼,我們會(huì)看到四個(gè)重載方法
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)
通過(guò)這些發(fā)放的分析谚殊,我們得出下面的分析
生命周期的作用域(1.Application丧鸯, 2.Activity, 3.Fragment)
with 參數(shù) | 作用域 | 代碼中線程 |
---|---|---|
Application | 子線程使用with | |
View | Fragment/Activity | 主線程 |
Fragment | Fragment | 主線程 |
Activity | Activity | 主線程 |
FragmentActivity | Activity | 主線程 |
ServiceContext/ApplicationContext | Application | 主線程 |
一共分為兩種:
第一種是作用域Application嫩絮,它的生命周期是全局 的丛肢,不搞空白Fragment綁定Activity/Fragment
第二種是作用域非Application,它的生命周期是絮记,專門搞空白Fragment綁定 Activity/Fragment
生成默認(rèn)隱藏fragment 摔踱,我們發(fā)現(xiàn)有著幾個(gè)方法
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<FragmentManager, SupportRequestManagerFragment> pendingSupportRequestManagerFragments =
new HashMap<>();
supportFragmentGet----getSupportRequestManagerFragment
- 從FragmentManager中獲取SupportRequestManagerFragment
SupportRequestManagerFragment current =
getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
2.從該 Fragment 中獲取 RequestManager
RequestManager requestManager =current.getRequestManager();
3.首次獲取虐先,則實(shí)例化 RequestManager
------> getSupportRequestManagerFragment
1.1 嘗試獲取 FRAGMENT_TAG 對(duì)應(yīng)的 Fragment
1.2 嘗試從臨時(shí)記錄中獲取Fragment
如果為獲取到
1.3 current==null---實(shí)例化 Fragment
1.3.1 創(chuàng)建對(duì)象SupportRequestManagerFragment
1.3.2 如果父層可見(jiàn)怨愤,則調(diào)用 onStart() 生命周期
1.3.3 臨時(shí)記錄映射關(guān)系pendingSupportRequestManagerFragments.put(fm, current)
1.3.4 提交 Fragment 事務(wù)
1.3.5 post 一個(gè)消息
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
-》post 一個(gè)消息分析: RequestManagerRetriever 本身實(shí)現(xiàn)了Handler的callback
handleMessage中
case ID_REMOVE_SUPPORT_FRAGMENT_MANAGER:
FragmentManager supportFm = (FragmentManager) message.obj;
key = supportFm;
removed = pendingSupportRequestManagerFragments.remove(supportFm);
break;
就是為了避免 SupportRequestManagerFragment 在一個(gè)作用域中重復(fù)創(chuàng)建。
因?yàn)?commitAllowingStateLoss() 是將事務(wù) post 到消息隊(duì)列中的蛹批,也就是說(shuō)撰洗,事 務(wù)是異步處理的篮愉,而不是同步處理的。假設(shè)沒(méi)有臨時(shí)保存記錄差导,一旦在事務(wù)異步等待 執(zhí)行時(shí)調(diào)用了 Glide.with(...) 若河,就會(huì)在該作用域中重復(fù)創(chuàng)建 Fragment勺择。
生命周期的監(jiān)聽(tīng)機(jī)制
Glide內(nèi)部會(huì)在 Activity/Fragment生命周期監(jiān)聽(tīng),網(wǎng)絡(luò)變化監(jiān)聽(tīng),自動(dòng)取消加 載或者重新加載
框架為每個(gè)Activity 和 Fragment 作用域創(chuàng)建了 一個(gè)無(wú)UI的Fragment
分析這個(gè)空Fragment---》 SupportRequestManagerFragment.java
看下我們比較關(guān)心的代碼
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
- 實(shí)例化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);
}
- 默認(rèn)工廠接口實(shí)現(xiàn)
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 源碼我們關(guān)心的部分
final Lifecycle lifecycle;
public RequestManager(
@NonNull Glide glide,
@NonNull Lifecycle lifecycle,
@NonNull RequestManagerTreeNode treeNode,
@NonNull Context context) {
......
this.lifecycle = lifecycle;
this.requestTracker = requestTracker;// 生命周期回調(diào)
。仍劈。娄猫。
if (Util.isOnBackgroundThread()) {
mainHandler.post(addSelfToLifecycle);
} else {// 添加監(jiān)聽(tīng)
lifecycle.addListener(this);
}
。外冀。寡键。
public synchronized void onDestroy() {
targetTracker.onDestroy();
......
lifecycle.removeListener(this);//remove 監(jiān)聽(tīng)
}
}
實(shí)例化 RequestManager 時(shí)需要一個(gè) Lifecycle對(duì)象,這個(gè)對(duì)象是 在無(wú)界面 Fragment 中創(chuàng)建的雪隧,當(dāng) Fragment 的生命周期變化時(shí)西轩,就是通過(guò)這個(gè) Lifecycle 對(duì)象將事件分發(fā)到RequestManager
生命周期的回調(diào)
RequestsManger 收到的回調(diào)ConnectivityMonitor
public interface LifecycleListener {
void onStart();
void onStop();
void onDestroy();
}
Activity/Fragment 不可見(jiàn)時(shí)暫停請(qǐng)求 (onStop() ) 函數(shù) Activity/Fragment 可見(jiàn)時(shí)恢復(fù)請(qǐng)求 (onStart() ) 函數(shù) Activity/Fragment 銷毀時(shí)銷毀請(qǐng)求 (onDestroy() )函數(shù)
---》 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);
}