场景:
- 在最近的项目中有用到这样的一个常见的使用场景: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
网友评论