在使用Fragment过程中遇到的坑(一)切换判断界面是否可见,关于onhiddenchanged和setUserVisibleHint函数

背景:项目中每个页面多个地方使用到Fragment,有的是在viewpager中,有的自己进行管理;项目运行一段时间后想对fragment进行懒加载处理,很早之前只对ViewPager中的Fragment进行过处理,结果在处理过程中遇到的一些问题。

先看一段代码

public abstract class BaseFragment extends Fragment {

    private boolean isFirstVisible = true;
    private boolean isFirstInvisible = true;

    private boolean isViewCreated;
    private boolean isUIVisible;

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        isViewCreated = true;
        lazyLoad(); // 执行懒加载,因为无法确定setUserVisibleHint和onViewCreated哪个方法先执行,因此两个方法里面都需要调用lazyLoad
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isVisibleToUser) {
            isUIVisible = true; //当前fragment可见
            if (isFirstVisible) {
                //如果是第一次可见,则进行懒加载
                isFirstVisible = false;
                lazyLoad();
            } else {
                //不是第一次可见,则调用onUserVisible()
                onUserVisible();
            }
        } else {
            isUIVisible = false;
            if (isFirstInvisible) {
                isFirstInvisible = false;
                //第一次不可见
                onFirstUserInvisible();
            } else {
                //非第一次不可见
                onUserInvisible();
            }
        }
    }

    private void lazyLoad() {
        if (isViewCreated && isUIVisible) { //需要进行双重判断,避免因为setUserVisibleHint先于onViewCreaetd调用时,出现空指针
            LogUtils.e( this.getClass().getSimpleName()  + "lazyLoad");
//            initViewsAndEvents();
            onFirstUserVisible();  //进行初次可见时的加载
        }else {
            LogUtils.e( this.getClass().getSimpleName()  + ">>>>isViewCreated:" + isViewCreated + "------>>>>>isUIVisible:" + isUIVisible);
        }
    }

    protected abstract void onFirstUserVisible();

    protected abstract void onUserVisible();

    protected abstract void onFirstUserInvisible();

    protected abstract void onUserInvisible();
}

一般ViewPager+Fragment的时候,主要使用到了setUserVisibleHint()方法进行判断Fragment是否可见,来进行懒加载处理。

但是
但是
但是
在某些场景中setUserVisibleHint()竟然没有执行~~~~:在未使用Viewpager,而是自己通过FragmentTransaction 对Fragment进行add hide show操作,setUserVisibleHint()方法没有被调用。原因是hide()和show()方法调用时,Fragment不走任何的生命周期。

这时候突然发现另外一个Fragment方法onhiddenchanged(),该方法用于判断fragment显隐,正好切合hide show操作。

public abstract class LazyFragment extends BaseFragment {
    public static final String TAG = LazyFragment.class.getSimpleName();


    private boolean hasLoaded = false;

    private boolean isCreated = false;

    private boolean isVisibleToUser = false;
    private View view;

    @Override
    protected void initViews(View view, @Nullable Bundle savedInstanceState) {
        isCreated = true;
        this.view = view;
        lazyLoad(this.view, savedInstanceState);
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        this.isVisibleToUser = isVisibleToUser;//注:关键步骤
        super.setUserVisibleHint(isVisibleToUser);
        lazyLoad(view, null);
    }

    private void lazyLoad(View view, Bundle savedInstanceState) {
        if (!isVisibleToUser || hasLoaded || !isCreated) {
            return;
        }
        lazyInitView(view, savedInstanceState);
        hasLoaded = true;//注:关键步骤,确保数据只加载一次
    }

    public abstract void lazyInitView(View view, Bundle savedInstanceState);

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        isCreated = false;
        hasLoaded = false;
    }

}

然后对BaseFragment进行进一步封装,应对各种情况。

总结

onhiddenchanged()

用FragmentTransaction来控制fragment的hide和show时,那么这个方法就会被调用。每当你对某个Fragment使用hide或者是show的时候,那么这个Fragment就会自动调用这个方法。

(使用情况:你自己去管理Fragment,而不是用viewpager管理的时候)

setUserVisibleHin()

在使用viewpager的时候,viewpager内部有个提前缓存的机制(默认是提前缓存一页),比如你在看第一个Fragment的时候,隔壁的Fragment已经创建好了,但此时的状态却是不可见的。

但是这时候Fragment不会去调用上面说的onhiddenchanged方法,只会调用setUserVisibleHint这个方法。

参考

fragment 切换判断界面是否可见 setUserVisibleHint和onHiddenChanged使用场景

关于onhiddenchanged和setUserVisibleHint函数的知识

支付宝发红包啦!即日起还有机会额外获得余额宝消费红包!长按复制此消息,打开最新版支付宝就能领取!q1iF0j95U0

在使用Fragment过程中遇到的坑(一)切换判断界面是否可见,关于onhiddenchanged和setUserVisibleHint函数_第1张图片
微信图片_20180712133728.png

你可能感兴趣的:(在使用Fragment过程中遇到的坑(一)切换判断界面是否可见,关于onhiddenchanged和setUserVisibleHint函数)