先說一下,setUserVisibleHint方式已經不推薦使用了,替代它的方案就是setMaxLifecycle,這裏不再具體講解setMaxLifecycle(講我也不會哈哈)
推薦一篇文章:setMaxLifecycle講解,想具體瞭解可以看看。
效果:
setMaxLifecycle方式實現fragment懶加載:(需要使用androidx)
第一步:
爲FragmentPagerAdapter的構造函數 添加參數FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT
FragmentPagerAdapter適配器構造方法中有一個behavior參數(下面代碼的第二個參數),
把這個參數的值設置爲:FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT
這樣就使用setMaxLifecycle來限制了fragment的生命週期,fragment的onReseume()只有當fragment顯示在屏幕上時纔會執行,這樣就可以把加載數據的方法放在onResume()方法中來實現懶加載了
這樣就完成了第一步(下面有完整代碼)
FragmentPagerAdapter(FragmentManager fm, int behavior, List<BaseFragment> fragmentList) // 看第二個參數
第一步完整代碼:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = findViewById(R.id.viewpager);
List<BaseFragment> fragmentList = new ArrayList<>();
fragmentList.add(new Fragment1());
fragmentList.add(new Fragment2());
fragmentList.add(new Fragment3());
// 爲MyPagerAdapter適配器設置FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT 參數
MyPagerAdapter myPagerAdapter = new MyPagerAdapter(getSupportFragmentManager(),
FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT, fragmentList);
viewPager.setAdapter(myPagerAdapter);
// 設置預加載爲3頁,來測試懶加載是否成功
viewPager.setOffscreenPageLimit(3);
}
// 適配器
public class MyPagerAdapter extends FragmentPagerAdapter {
List<BaseFragment> fragmentList;
MyPagerAdapter(@NonNull FragmentManager fm, int behavior, List<BaseFragment> fragmentList) {
super(fm, behavior);
this.fragmentList = fragmentList;
}
@NonNull
@Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
@Override
public int getCount() {
return fragmentList.size();
}
}
}
第二步:
封裝一個BaseFragment:通過它的onReseume()方法來控制具體每個fragment的數據懶加載
第二步完整代碼:
public abstract class BaseFragment extends Fragment {
private boolean isOk = false; // 是否完成View初始化
private boolean isFirst = true; // 是否爲第一次加載
public View view;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
view = getMyView(inflater, container, savedInstanceState); // 獲取子fragment的view
initView();
isOk = true; // 完成initView後改變view的初始化狀態爲完成
return view;
}
// 子fragment初始化view的方法
abstract void initView();
// 獲取子fragment的view
abstract View getMyView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState);
@Override
public void onResume() {
super.onResume();
initLoadData(); // 在onResume中進行數據懶加載
}
private void initLoadData() {
if (isOk && isFirst) { // 加載數據時判斷是否完成view的初始化,以及是不是第一次加載此數據
loadData();
isFirst = false; // 加載第一次數據後改變狀態,後續不再重複加載
}
}
// 子fragment實現懶加載的方法
abstract void loadData();
}
第三步:
具體fragment如何運用
第三步具體代碼:
public class Fragment1 extends BaseFragment { // 繼承第二步中的BaseFragment,實現對應方法
@Override
void initView() { //此處進行view初始化
TextView textView = view.findViewById(R.id.text_fragment1);
}
@Override //此處把當前fragment的視圖進行初始化
View getMyView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment1, container, false);
}
@Override
void loadData() { //此處是實現了懶加載的加載數據的方法
Toast.makeText(getContext(), "123", Toast.LENGTH_SHORT).show();
}
}
setUserVisibleHint方式實現懶加載:(只是更改了第二步與第一步中的一些方法)
第二步改爲:
public abstract class BaseLazyFragment extends BaseFragment {
private boolean isFirst = true; // 是否爲第一次加載
private boolean isView = false; //view是否加載完(防止空指針)
private boolean isisVisible = false; //是否對用戶可見
public View view;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
view = getMyView(inflater, container, savedInstanceState); // 獲取子fragment的view
initView();
isView = true;
myLoadData(); //加載數據
return view;
}
// 子fragment初始化view的方法
public abstract void initView();
// 獲取子fragment的view
public abstract View getMyView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState);
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
isisVisible = true;
myLoadData();
} else {
isisVisible = false;
}
}
private void myLoadData() {
if (isFirst && isisVisible && isView) { // 加載數據時判斷是否完成view的初始化,以及是不是第一次加載此數據,以及用戶是否切換到了這個fragment
loadData();
isFirst = false; // 加載第一次數據後改變狀態,後續不再重複加載
}
}
// 子fragment實現懶加載的方法
public abstract void loadData();
}
第一步中MyPagerAdapter的構造方法改爲下面的:
// 適配器
public class MyPagerAdapter extends FragmentPagerAdapter {
List<BaseFragment> fragmentList;
MyPagerAdapter(@NonNull FragmentManager fm,List<BaseFragment> fragmentList) {
super(fm);
this.fragmentList = fragmentList;
}
@NonNull
@Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
@Override
public int getCount() {
return fragmentList.size();
}
}