美文网首页
ViewPager1预加载下的Fragment懒加载策略

ViewPager1预加载下的Fragment懒加载策略

作者: 我默默 | 来源:发表于2020-10-26 08:21 被阅读0次

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);

}

相关文章

网友评论

      本文标题:ViewPager1预加载下的Fragment懒加载策略

      本文链接:https://www.haomeiwen.com/subject/ruhppktx.html