ViewPager+Fragment可以非常高效地实现动态编辑多个相似页面。
但是ViewPager会预加载Fragment(左右n(n>=1)个页面) ,导致Fragment的onResume()和onPause()可能不会按预期的执行。在接入友盟统计时,页面统计需要Activity和Fragment的onResume()和onPause()配对,但ViewPager中的Fragment会出现调用顺序问题。
无论如何,对于Fragment,我的期望是显示的时候执行onResume(),隐藏的时候执行onPause()
检测Fragment是否显示有2个方法:
- setUserVisibleHint(boolean isVisibleToUser)
- getUserVisibleHint()
ViewPager中的Fragment本身做不到显示的时候执行onResume(),隐藏的时候执行onPause(),所以我要设置方法,让这个方法来做到这样的效果:
/**
* 替代具有不确定性的onResume()(ViewPager可能会让多个fragment执行onResume(),但有些fragment执行后是不可见状态的)
* 我需要的是执行onResume后,确定是可见状态的方法
*/
protected void onResumeVisible() {}
/**
* 替代具有不确定性的onPause()(ViewPager可能会让多个fragment执行onPause())
* 我需要的是执行onPause前,确定执行onResume()
*/
protected void onPauseInVisible() {}
当然,优化Fragment基本考虑到懒加载,顺便实现。全部代码
/**
* Copyright (C)
* FileName: BaseFragment
* Author: wudengwei
* Date: 2018/12/17 20:15
* Description: 解决ViewPager中使用显示与隐藏和onResume()与onPause()不一致问题
*/
public class BaseFragment extends Fragment {
protected Activity mActivity;
//是否第一次可见
private boolean isFirstVisible = true;
//是否可见
private boolean isVisible = false;
/**
* onResume是否已经执行,fragment在ViewPager中
* 第一次创建时(预加载)不管可不可见,都会执行一次生命周期
* isFirstOnResume=false表示预加载或当前显示的fragment执行了onResume()
* isFirstOnResume=false,fragment再次显示时,当做执行了onResume()
*/
private boolean isFirstOnResume = true;
/**
* 作用于onResume()在显示状态下执行后,fragment隐藏时执行对应的onPause()
* 避免其他页面的onPause()执行
* 是否可以使用isVisible代替?
*/
private boolean isOnResumeVisible = false;
@Override
public void onAttach(Context context) {
this.mActivity = (Activity) context;
super.onAttach(context);
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (getView() == null)
return;
/*可见回调方法*/
if (isVisible != isVisibleToUser)
onVisibleChange(isVisibleToUser,isFirstVisible);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
isFirstVisible = true;
isVisible = false;
isFirstOnResume = true;
isOnResumeVisible = false;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (getUserVisibleHint()) {
/*可见,是否第一次*/
onVisibleChange(true,isFirstVisible);
}
}
@Override
public void onResume() {
super.onResume();
if (isFirstOnResume) {
isFirstOnResume = false;
}
if (getUserVisibleHint() && !isOnResumeVisible) {//onResume()在可见状态下调用
isOnResumeVisible = true;
onResumeVisible();
}
}
@Override
public void onPause() {
super.onPause();
//onResume()在可见状态下调用后,进入onPause()
if (!isFirstOnResume && isOnResumeVisible) {
isOnResumeVisible = false;
onPauseInVisible();
}
}
@Override
public void onDestroy() {
super.onDestroy();
isFirstVisible = true;
isVisible = false;
isFirstOnResume = true;
}
/*是否可见回调方法*/
protected void onVisibleChange(boolean isVisible,boolean firstVisible) {
this.isVisible = isVisible;
if (firstVisible) {
onLazyLoad();
isFirstVisible = false;
}
if (isVisible && !isFirstOnResume && !isOnResumeVisible) {//isFirstOnResume=false表示fragment预加载,onResume()在可见状态下调用
isOnResumeVisible = true;
onResumeVisible();
}
if (!isVisible && !isFirstOnResume && isOnResumeVisible) {
isOnResumeVisible = false;
onPauseInVisible();
}
}
/**
* 懒加载(第一次可见)
*/
protected void onLazyLoad() {
}
/**
* 替代具有不确定性的onResume()(ViewPager可能会让多个fragment执行onResume(),但有些fragment执行后是不可见状态的)
* 我需要的是执行onResume后,确定是可见状态的方法
*/
protected void onResumeVisible() {}
/**
* 替代具有不确定性的onPause()(ViewPager可能会让多个fragment执行onPause())
* 我需要的是执行onPause前,确定执行onResume()
*/
protected void onPauseInVisible() {}
}
源码:https://github.com/wudengwei/TabIndicatorLayout