public abstract class MyLazyFragment extends Fragment {
FragmentDelegater mFragmentDelegater;
private View rootView;
//TODO Step1 : View是否已经经历过 初始化了,oncreateView 还没有走,setUserVisibleHint直接跳出 不用分发
// 目标不初始化不加载,顺带预防bug:再 onFragmentLoadStop中操作UI
private boolean isViewCreated = false;
//TODO Step3 :记录上次的状态 ,防止:T1->T2->T3------>T1 如果缓存1,则T1已经被回收掉了,会重新走onCreateView---->setUserVisibleHint这么一来就加载两次了 、
// 所以需要记录上次的状态:确定是从 unVisible--->Visible再去加载,
private boolean isLastStateVisible = false;
//TODO Step4 :主要就是针对 Fragment--goto-->Activity--goback-->Fragment 之后需要更新Fragment的情况 主要借助onResume+onPause方法去做
// TODO Step5 :终于接近真实的场景了 俄罗斯套娃的viewPager+Fragment(Viewpager+ Fragment) 主要是外层对内层部分发啊 egg-pain......
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
E("onCreateView: ");
rootView = inflater.inflate(getLayoutRes(), container, false);
isViewCreated = true;
initView(rootView);
functionStep2();
return rootView;
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
//TODO step1
if(!isViewCreated) return;
if (isVisibleToUser && !isLastStateVisible) {
dispatchUserVisibleHint(true);
} else if(!isVisibleToUser &&isLastStateVisible){
dispatchUserVisibleHint(false);
}
}
//TODO 对Fragment加载进行分发
private void dispatchUserVisibleHint(boolean visibleState) {
isLastStateVisible = visibleState;
// todo Step5===========
if(visibleState && isParentInvisible()){
return;
}
if (visibleState) {
onFragmentLoad();
//TODO Step5:为了解决第二个问题,T1 到 T2 T2里面嵌套的ViewPager的Fragment默认不会分发执行
// ==========在双重ViewPager嵌套的情况下,第一次滑到Frgment 嵌套ViewPager(fragment)的场景的时
// ==========此时只会加载外层Fragment的数据,而不会加载内嵌viewPager中的fragment的数据,因此,我们
// ==========需要在此增加一个当外层Fragment可见的时候,分发可见事件给自己内嵌的所有Fragment显示
dispatchChildVisibleState(true);
} else {
onFragmentLoadStop();
dispatchChildVisibleState(false);
}
}
public void onFragmentLoadStop() {
E("onFragmentLoadStop");
}
public void onFragmentLoad() {
E("onFragmentLoad");
}
//todo Step5==========================================================================
private boolean isParentInvisible(){
Fragment parentFragment = getParentFragment();
if(parentFragment instanceof MyLazyFragment){
MyLazyFragment fragment = (MyLazyFragment) parentFragment;
return !fragment.isLastStateVisible;
}
return false;
}
private void dispatchChildVisibleState(boolean state) {
FragmentManager fragmentManager = getChildFragmentManager();
List<Fragment> fragments = fragmentManager.getFragments();
for (Fragment fragment :fragments){
if(fragment instanceof MyLazyFragment && !fragment.isHidden() && fragment.getUserVisibleHint()){
((MyLazyFragment) fragment).dispatchUserVisibleHint(state);
}
}
}
// Todo Step4=======onResume+onPause==============================================================
@Override
public void onResume() {
super.onResume();
E("onResume");
//todo step4 不可见 到 可见 变化过程 说明可见
if (getUserVisibleHint() && !isLastStateVisible) {
dispatchUserVisibleHint(true);
}
}
@Override
public void onPause() {
super.onPause();
E("onPause");
//todo step4 不可见 到 可见 变化过程 说明可见
if (getUserVisibleHint() && isLastStateVisible) {
dispatchUserVisibleHint(false);
}
}
private void functionStep2() {
//TODO Step2:由于ViewPager的预加载导致的-------解释了懒加载的,导致我们监听函数的顺序
// 表象为:
// MyFragment -> setUserVisibleHint------------->false
// 1 fragment setUserVisibleHint: false
// MyFragment -> setUserVisibleHint------------->false
// 2 fragment setUserVisibleHint: false
// MyFragment -> setUserVisibleHint------------->true
// 1 fragment setUserVisibleHint: true
// ~~~~~~~~~~~~~~~~~下面就是分段执行步骤~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 1 fragment onAttach:
// 1 fragment onCreate:
// 2 fragment onAttach:
// 2 fragment onCreate:
// MyFragment -> onCreateView:
// 1 fragment initView
// MyFragment -> onResume
// 1 fragment onResume:
// MyFragment -> onCreateView:
// 2 fragment initView:
// MyFragment -> onResume
// 2 fragment onResume:
// ~~~~~从这日日志中可以看到MyFragment集成1/2,onAttach和onCreate速度很快都加进来,之后才执行的onCreateView~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 第一部分执行--->首次打开页面T1,T2的setUserVisibleHint=false已经执行,然后再执行T1的setUserVisibleHint=true ,
// 第二部分执行--->T1:onAttach onCrete onCreateView || T2: onAttach onCrete,导致我们的分发Step1条件都不满足,所以需要手动分发一下
// 这里 如果要彻底明白只好上才艺---------------------------:
// Viewpager.setAdapter---->populate()--->this.mAdapter.startUpdate---->addNewItem(----this.mAdapter.instantiateItem(-----setUserVisibleHint))
// 以上流程就解释了为什么在Fragment还没有初始化就是开始了调用了setUserVisibleHint 上面执行之后会确定当前的item 也就是--addNewItem--->this.mAdapter.setPrimaryItem
// setPrimaryItem(-----setUserVisibleHint) 这里就会有调用一下当前显示item的 setUserVisibleHint
// 以上执行完毕之后会调用this.mAdapter.finishUpdate --->开始调用FragmentTransaction事务管理,所以看到现象就是先
// 才艺结束-----------------------------------------------
// 事实上 :ViewPager,操纵的是setUserVisibleHint,优先于Fragment生命周期的执行,所以导致了onCreate 中需要再次分发
if(getUserVisibleHint()){
setUserVisibleHint(true);
}
}
public void setFragmentDelegater(FragmentDelegater mFragmentDelegater) {
this.mFragmentDelegater = mFragmentDelegater;
}
private void E(String s) {
if (mFragmentDelegater != null)
mFragmentDelegater.dumpLifeCycle(s);
}
protected abstract int getLayoutRes();
protected abstract void initView(View rootView);
}
网友评论