ViewPager+TabLayout+Fragment懶載入機制完全解析
ViewPager+TabLayout+Fragment懶載入機制完全解析
在Fragment和ViewPager配合使用的時候,ViewPager會使用預載入機制,使得我們在沒有跳轉到對應頁面時,可能已經載入好了,這是個非常不好的使用者體驗,浪費使用者的流量。本篇文章主要講解在ViewPager+TabLayout+Fragment的情況下,Fragment的懶載入機制的實現以及專案封裝情況。
一、setUserVisibleHint(boolean isVisibleToUser)
setUserVisibleHint(boolean isVisibleToUser)是Fragment中的一個回撥函式。當前Fragment可見時,setUserVisibleHint()回撥,其中isVisibleToUser=true。當前Fragment由可見到不可見或例項化時,setUserVisibleHint()回撥,其中isVisibleToUser=false。
setUserVisibleHint(boolean isVisibleToUser)呼叫時機
①在Fragment例項化,即在ViewPager中,由於ViewPager預設會預載入左右兩個頁面。此時預載入頁面回撥的生命週期流程:setUserVisibleHint() -->onAttach() --> onCreate()-->onCreateView()--> onActivityCreate() --> onStart() --> onResume()
此時,setUserVisibleHint() 中的引數為false,因為不可見。
②在Fragmetn可見時,即ViewPager中滑動到當前頁面時,因為已經預載入過了,之前生命週期已經走到onResume() ,所以現在只會回撥:setUserVisibleHint() 。
此時,setUserVisibleHint() 中的引數為true,因為可見。
③在Fragment由可見變為不可見,即ViewPager由當前頁面滑動到另一個頁面,因為還要保持當前頁面的預載入過程,所以只會回撥:setUserVisibleHint()。
此時,setUserVisibleHint() 中的引數為false,因為不可見。
④由TabLayout直接跳轉到一個未預載入的頁面,此時生命週期的回撥過程:setUserVisibleHint() -->setUserVisibleHint() -->onAttach() --> onCreate()-->onCreateView()--> onActivityCreate() --> onStart()
--> onResume()
回撥了兩次setUserVisibleHint() ,一次代表初始化時,傳入引數是false,一次代表可見時,傳入引數是true。這種情況比較特殊。
總結:無論何時,setUserVisibleHint()都是先於其他生命週期的呼叫,並且初始化時呼叫,可見時呼叫,由可見轉換成不可見時呼叫,一共三次時機。
二、封裝實現懶載入機制
載入網路的情況:
①setUserVisibleHint()中引數為true,即Fragment可見;
②onCreateView()方法呼叫完畢,返回rootView,防止造成空指標問題;
③第一次呼叫網路載入,之前沒載入過,即isFirst = false(有些彆扭,可以改成true,對應程式碼做下修改)。
滿足以上條件,載入網路請求。
取消載入網路的情況:
①setUserVisibleHint()中引數由true變為false,即Fragment由可見變為不可見;
②不是第一次呼叫網路載入,之前載入過,即isFirst = true。
滿足以上兩者條件(只滿足第一點也可以),取消網路請求。
封裝程式碼
在BaseFragment中進行封裝
其中isFragment表示當前Fragment的可見情況
isFirst表示是否已經載入過
onFragmentVisibleChange()是一個可繼承的空方法,子類實現,傳入true,代表載入網路,傳入false,代表取消網路載入。
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
isFragmentVisible = true;
}
if (rootView == null) {
return;
}
//可見,並且沒有載入過
if (!isFirst&&isFragmentVisible) {
onFragmentVisibleChange(true);
return;
}
//由可見——>不可見 已經載入過
if (isFragmentVisible) {
onFragmentVisibleChange(false);
isFragmentVisible = false;
}
}
protected void onFragmentVisibleChange(boolean isVisible) {
}
其中有一種特殊情況不能滿足上述程式碼中的條件進行網路載入。
特殊情況:當TabLayout跳轉到一個沒有預載入過的Fragment,連續呼叫兩次setUserVisibleHint方法,但此時rootView為空,不能進行載入。需要在onCreateView()方法最後判斷是否進行網路載入,然後呼叫onFragmentVisibleChange(true)方法
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
.................
//可見,但是並沒有載入過
if (isFragmentVisible && !isFirst) {
onFragmentVisibleChange(true);
}
return rootView;
}
子類實現的例項:
@Override
protected void onFragmentVisibleChange(boolean isVisible) {
if(isVisible){
//可見,並且是第一次載入
mPresenter.requestPhotoList(SIZE,mStartPage);
LoadingDialog.showDialogForLoading(getActivity());
}else{
//取消載入
RxDisposeManager.get().cancel("photoList");
LoadingDialog.cancelDialogForLoading();
}
}
三、效果實現
上圖效果可以看出實現了懶載入,並且再次滑動回對應Fragment,也不會載入,通過下拉重新整理才能更新資料,減少流量的耗費。
上圖效果可以看出,當TabLayout直接跳轉到沒有預載入的頁面,也可以實現懶載入,效果一樣。
小夥伴們有沒有很心動,下面有原始碼,歡迎參考使用!
只需要看BaseFragment部分即可
相關文章
- Handler訊息機制完全解析Handler解析
- Tablayout+Viewpager+Fragment組合使用以及懶載入機制TabLayoutViewpagerFragment
- SAP CRM WebClient UI和Hybris Commerce的懶載入機制WebclientUI
- 懶載入
- TabLayout+ViewPager+Fragment實現懶載入完全解決方案TabLayoutViewpagerFragment
- 懶載入和預載入
- iOS: 懶載入iOS
- 類載入機制
- Android訊息機制不完全解析(上) .Android
- Android訊息機制不完全解析(下) .Android
- 轉載Oracle SCN機制解析Oracle
- Spring 原始碼解析一:SpringMVC 的載入機制原始碼SpringMVC
- 兩道面試題帶你解析 Java 類載入機制面試題Java
- Spring5.0原始碼學習系列之淺談懶載入機制原理Spring原始碼
- 【譯】懶載入元件元件
- 圖片懶載入
- Vue元件懶載入Vue元件
- Ribbon - 懶載入
- vue路由懶載入Vue路由
- Vue 的懶載入Vue
- Swift中懶載入Swift
- hibernate懶載入
- spring 懶載入Spring
- 什麼是hibernate懶載入?什麼時候用懶載入?為什麼要用懶載入?(轉)
- 類的載入機制
- JVM:類載入機制JVM
- java類載入機制Java
- JVM類載入機制JVM
- ABP - 模組載入機制
- JVM 類載入機制JVM
- Vue 路由按需載入(路由懶載入)Vue路由
- 圖片預載入和懶載入
- Java 類載入器以及載入機制Java
- 虛擬機器類載入機制:類載入時機虛擬機
- 前端效能優化 --- 懶載入&預載入前端優化
- 單張圖片懶載入
- 圖片懶載入(IntersectionObserver)Server
- vue(18)路由懶載入Vue路由