Fragment实现类似activity onResume()功能,控制fragment可见与不可见

众所周知,fragment的onResume()和onPause()方法是和activity绑定在一起的,此时fragment的onResume方法并不能确定在fragment切换前后台时会调用,而app开发中经常会需要在前后台切换时做一些操作,在activity中一般直接在onResume()中操作,而fragment中似乎没有这么方便的原生方法。


和别人合作做某一项目的时候,发现他的fragment中是使用setUserVisibeHint来区分fragment的显示与否,经研究发现,当使用ViewPager+Fragment组合的时候会多次调用setUserVisibleHint方法,然而此方法却有很多缺点,摘一段源码中的note:

 

* <strong>Note:</strong> This method may be called outside of the fragment lifecycle.
* and thus has no ordering guarantees with regard to fragment lifecycle method calls.


既然有这些缺点,那么在这个方法中来进行数据加载和控件的操作 必然是不安全的


一.简单情景下的封装

于是我们就想要封装一个简单易用的方法来进行数据加载和控件操作

暂时先不管ViewPager+Fragment组合的情况,在一般使用Fragment的情景中 

通过 onResume(),onPause(),onHiddenChanged()这三个方法来实现了我们的需求。其中onResume()和onPause()方法是和绑定的activity的生命周期绑定的,另外onHiddenChanged()是在fragment是否可见状态改变的时候调用的,于是就有了以下的解决方案,不再赘述,直接上代码:

public abstract class BaseFragment  extends Fragment {
     
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
      
    }

  
    /**
     * fragment可见的时候操作,取代onResume,且在可见状态切换到可见的时候调用
     */
    protected void onVisible() {
    
    }

    /**
     * fragment不可见的时候操作,onPause的时候,以及不可见的时候调用
     */
    protected void onHidden() {

    }


    @Override
    public void onResume() {//和activity的onResume绑定,Fragment初始化的时候必调用,但切换fragment的hide和visible的时候可能不会调用!
        super.onResume();
        if (isAdded() && !isHidden()) {//用isVisible此时为false,因为mView.getWindowToken为null
            onVisible();
        }
    }

    @Override
    public void onPause() {
        if (isVisible())
            onHidden();
        super.onPause();
    }

    @Override
    public void onHiddenChanged(boolean hidden) {//默认fragment创建的时候是可见的,但是不会调用该方法!切换可见状态的时候会调用,但是调用onResume,onPause的时候却不会调用
        super.onHiddenChanged(hidden);
        if (!hidden) {
            onVisible();
        } else {
            onHidden();
        }
    }
代码中的注释已经很详尽了,在fragment可见的时候会调用onVisible()不可见的时候会调用onHidden(),继承这个baseFragment你就可以快乐的使用onVisible()和onHidden()来进行数据加载咯~~

注意:如果您的fragment是配合viewpager使用的,因为viewpager当前页的左右两个fragment都会默认加载,且切换的时候并不会调用onhiddenChanged()方法,所以我上面的方法在viewpager+fragment的组合下有一定的缺陷(例如:viewpager中有两个fragment,当从别的页面回到该viewpager所在页面时,两个fragment都会调用onvisible方法,而在左右滑动两个fragment的时候并不会调用onvisible和onhidden)
因此就有了下面的 加强版 适配ViewPager  setUserVisibleHint()的BaseFragment


二.包括ViewPager+Fragment的复杂情景通用封装

代码如下:
public abstract class BaseFragment extends Fragment {
    protected final String TAG = this.getClass().getSimpleName();

    /**
     * Fragment当前状态是否可见
     */
    protected boolean isVisible = false;
    /**
     * Fragment的view是否已创建
     */
   protected boolean mIsViewCreated = false;

   @Override 
   public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 
        View view = inflater.inflate(R.layout.xxx,container,false);
        System.out.println(TAG + "--onCreateView");
        mIsViewCreated = true;
        return view;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        System.out.println(TAG + "--onDestroyView");
        mIsViewCreated = false;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        System.out.println(TAG + "--onDestroy");
    }

 
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (!mIsViewCreated)//view没有创建的时候不进行操作
            return;

        if (getUserVisibleHint()) {
            if (!isVisible) {//确保在一个可见周期中只调用一次onVisible()
                isVisible = true;
                onVisible();
            }
        } else {
            if (isVisible) {
                isVisible = false;
                onHidden();
            }
        }
    }


    /**
     * 可见
     */
    protected void onVisible() {
     
    }

    /**
     * fragment不可见的时候操作,onPause的时候,以及不可见的时候调用
     */
    protected void onHidden() {

    }


    @Override
    public void onResume() {//和activity的onResume绑定,Fragment初始化的时候必调用,但切换fragment的hide和visible的时候可能不会调用!
        super.onResume();
        System.out.println(TAG + "--Base onResume");
        if (isAdded() && !isHidden()) {//用isVisible此时为false,因为mView.getWindowToken为null
            onVisible();
            isVisible = true;
        }
    }

    @Override
    public void onPause() {
        System.out.println(TAG + "--Base onPause");
        if (isVisible()||isVisible) {
            onHidden();
            isVisible = false;
        }
        super.onPause();
    }

    @Override
    public void onHiddenChanged(boolean hidden) {//默认fragment创建的时候是可见的,但是不会调用该方法!切换可见状态的时候会调用,但是调用onResume,onPause的时候却不会调用
        super.onHiddenChanged(hidden);
        System.out.println(TAG + "--Base onHiddenChanged:" + hidden);
        if (!hidden) {
            onVisible();
            isVisible = true;
        } else {
            onHidden();
            isVisible = false;
        }
    }
 }

此时 一样在继承的Fragment中 直接使用  onVisible()  以及 onHidden() 即可,此加强版适用于所有使用到fragment的地方,使用viewPager+fragment的亲们 可以愉快的开发啦~~



如果您有更好的方法,还请指教哦~

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值