美文网首页微信开发运营程序员
Fragment配合ViewPager时的OnResume调用时

Fragment配合ViewPager时的OnResume调用时

作者: longforus | 来源:发表于2017-04-07 20:24 被阅读0次

    场景:

    • 在最近的项目中有用到这样的一个常见的使用场景:Activity内包含一个ViewPager,里面装了几个Fragment,进行切换.在第三个ViewPager中,又做了一个postDelayed(Runable)实现自动轮播的轮播图.
    • 我想完成这样的一个需求:在第三个Fragment展现在眼前的时候开始自动轮播,一旦切换到别的Activity或者Fragment的时候停止轮播任务.还是可以节省一点资源的嘛.

    尝试:

    • 开始我就在第三个Fragment里面写上:

        @Override
        public void onResume() {
            super.onResume();
            Log.i(TAG, "onResume: ");
            if (asv !=null) {
                asv.startAutoScroll();//开始轮播
            }
        }
      
        @Override
        public void onPause() {
            super.onPause();
            Log.i(TAG, "onPause: ");
            if (asv !=null) {
                asv.stopAutoScroll();//结束轮播
            }
        }
      

    可是忘记了,Fragment在这里的生命周期调用并非是我跳转到这个Fragment时调用onResume,我离开时调用onPause.结果当然是不能完美的开始,结束自动轮播了.

    • 要解决这个问题先来复习一下在这种情况下,Activity和Fragment的生命周期调用顺序:


      1.png

    刚刚进入Activity并没有切换到第三个Fragment但是它的生命周期已经走完了创建的过程,在Activity的onResume调用后它就开始调用自己的生命周期方法.已经执行了onResume方法,当然这个时候,轮播图是还没有获取到数据,准备好的,自然不能开始自动轮播,想要切换到第三个Fragment的时候才调用它的onResume是自以为是的.而且在手动切换到第三个Fragment的时候并没有调用它的常用生命周期方法,停止轮播当然也不用想了.(非常用的不了解).

    顺便贴一下现在按back销毁Activity的生命周期:

    2.png

    在这个Activity销毁的时候才调用了Fragment销毁的生命周期.

    • 后面百度到说可以调用void setUserVisibleHint(boolean isVisibleToUser)方法,根据isVisibleToUser的状态来判断当前Fragment是否正显示在用户面前,起先我了解了一下他的调用顺序,竟然是在Fragment创建完成之前就会调用的,没有注意到他后面的调用时机.便没有尝试,而是采用监听ViewPager的onPageSelected方法来手动调用第三个Fragment的onResume方法来开始轮播,在跳转到其他Activity的时候系统调用第三个Fragment的onPause停止轮播,虽然有一些效果,但是感觉不完美.

    解决:

    • 后来还是尝试了一下setUserVisibleHint这个方法,发现他的调用顺序如下:


      3.png

      在首次调用时,虽然Fragment都还没有创建完成,但是isVisibleToUser是false,手动切换进入的时候是true,手动切换到别的Fragment的时候也进行了调用flase.如下使用就能够在切换到这个Fragment的时候开始轮播,切出去的时候停止轮播了:

        @Override
        public void setUserVisibleHint(boolean isVisibleToUser) {
            super.setUserVisibleHint(isVisibleToUser);
            if (asv == null) {
                return;
            }
            if (isVisibleToUser) {
                asv.startAutoScroll();
            } else {
                asv.stopAutoScroll();
            }
        }
      
    • 你以为这样就完了么?开始我也这么以为,但是这样做还是存在一些问题:从这个Fragment进入别的Activity的时候轮播并没有停止,一直继续着,postDelayed一直都在循环的发送.这是我不能接受的.就在不爽之间,忽然灵机一动.我又添了几行代码,变成了下面这样:

         private boolean mIsVisibleToUser = false;
      
        //1.在别的Fragment的时候mIsVisibleToUser肯定是false,不会调用开始轮播
        //2.在当然Fragment的时候mIsVisibleToUser肯定是true,所有我从这个Fragment
        //  进入别的Activity又退来的时候,就会开始轮播
        //3.从别的Fragment进入Activity再回来的时候触发onResume也会开始轮播,因为
        //  mIsVisibleToUser在切换到别的Fragment的时候就已经被置为false了
      
        @Override
        public void onResume() {
            super.onResume();
            if (asv !=null&&mIsVisibleToUser) {//在这里进行一下判断
                asv.startAutoScroll();
            }
        }
      
        @Override
        public void onPause() {
            super.onPause();
            if (asv !=null) {
                asv.stopAutoScroll();
            }
        }
        @Override
        public void setUserVisibleHint(boolean isVisibleToUser) {
            super.setUserVisibleHint(isVisibleToUser);
        
            mIsVisibleToUser = isVisibleToUser;//被调用时记录下状态
            if (asv == null) {
                return;
            }
            if (isVisibleToUser) {
                asv.startAutoScroll();
            } else {
                asv.stopAutoScroll();
            }
        }
      

    经过测试,感觉上完美的解决了这个问题,做下笔记,以后有没有不要太想当然,有线索就去尝试,实践是检验真理的唯一标准嘛.

    • void 2017-4-7 19:57:08

    相关文章

      网友评论

        本文标题:Fragment配合ViewPager时的OnResume调用时

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