问题
最近由于行情一波小牛,导致服务器带宽瓶颈。以前的客户端是一进入页面所有的api马上请求,现在需要把所有页面都改为延迟加载。
延迟加载的策略是viewpager在populate某个fraqment的时候会调用fragment的setUserVisibleHint(boolean visible)函数。这样我们根据这个状态来解决延迟加载的问题。如果viewpager嵌套的fragment,而fragment中又嵌套了viewpager,在代码中使用递归即可解决这个问题。
在fraqment中定义俩个方法,一个处理自身的visible状态,一个方法处理childFragment的visible状态,代码如下:
private void dispatchUserVisibleHint(boolean visible) {
//当前 Fragment 是 child 时候 作为缓存 Fragment 的子 fragment getUserVisibleHint = true
//但当父 fragment 不可见所以 currentVisibleState = false 直接 return 掉
// 这里限制则可以限制多层嵌套的时候子 Fragment 的分发
if (visible && isParentInvisible()) return;
//此处是对子 Fragment 不可见的限制,因为 子 Fragment 先于父 Fragment回调本方法 currentVisibleState 置位 false
// 当父 dispatchChildVisibleState 的时候第二次回调本方法 visible = false 所以此处 visible 将直接返回
if (currentVisibleState == visible) {
return;
}
currentVisibleState = visible;
if (visible) {
if (mIsFirstVisible) {
mIsFirstVisible = false;
onFragmentFirstVisible();
}
onFragmentResume();
dispatchChildVisibleState(true);
} else {
dispatchChildVisibleState(false);
onFragmentPause();
}
}
/**
* 当前 Fragment 是 child 时候 作为缓存 Fragment 的子 fragment 的唯一或者嵌套 VP 的第一 fragment 时 getUserVisibleHint = true
* 但是由于父 Fragment 还进入可见状态所以自身也是不可见的, 这个方法可以存在是因为庆幸的是 父 fragment 的生命周期回调总是先于子 Fragment
* 所以在父 fragment 设置完成当前不可见状态后,需要通知子 Fragment 我不可见,你也不可见,
*
* 因为 dispatchUserVisibleHint 中判断了 isParentInvisible 所以当 子 fragment 走到了 onActivityCreated 的时候直接 return 掉了
*
* 当真正的外部 Fragment 可见的时候,走 setVisibleHint (VP 中)或者 onActivityCreated (hide show) 的时候
* 从对应的生命周期入口调用 dispatchChildVisibleState 通知子 Fragment 可见状态
*
* @param visible
*/
private void dispatchChildVisibleState(boolean visible) {
FragmentManager childFragmentManager = getChildFragmentManager();
List fragments = childFragmentManager.getFragments();
if (!fragments.isEmpty()) {
for (Fragment child : fragments) {
if (child instanceof LazyLoadBaseFragment && !child.isHidden() && child.getUserVisibleHint()) {
((LazyLoadBaseFragment) child).dispatchUserVisibleHint(visible);
}
}
}
}
遇到的问题
我们现在所有的api请求都在onFragmentResume()
方法中执行,而onFragmentResume()
方法又是在setUserVisibleHint()
中执行。 而有很多presenter层的对象是在onCreateView()
方法中初始化,这样会导致调用时序问题,从而导致空指针异常.
下面是调查的日志,主要查看调用时序问题
2019-04-11 17:56:21.386 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: setUserVisibleHint -1 false
2019-04-11 17:56:21.386 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: setUserVisibleHint -1 false
2019-04-11 17:56:21.387 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: setUserVisibleHint 0 false
2019-04-11 17:56:21.387 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: setUserVisibleHint -1 true
2019-04-11 17:56:21.388 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: onCreate 2
2019-04-11 17:56:21.389 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: onCreate 3
2019-04-11 17:56:21.391 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: onCreateView 2
2019-04-11 17:56:21.408 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: onCreateView 3
2019-04-11 17:56:21.773 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: onDestroyView 0
2019-04-11 17:56:28.076 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: setUserVisibleHint -1 false
2019-04-11 17:56:28.076 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: setUserVisibleHint 2 false
2019-04-11 17:56:28.076 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: setUserVisibleHint -1 true
2019-04-11 17:56:28.077 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: onCreate 4
2019-04-11 17:56:28.079 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: onCreateView 4
2019-04-11 17:56:28.435 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: onDestroyView 2
2019-04-11 17:56:28.438 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: onDestroyView 1
2019-04-11 17:56:33.752 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: setUserVisibleHint -1 false
2019-04-11 17:56:33.753 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: setUserVisibleHint -1 false
2019-04-11 17:56:33.754 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: setUserVisibleHint 4 false
2019-04-11 17:56:33.754 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: setUserVisibleHint -1 true
2019-04-11 17:56:33.755 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: onCreate 0
2019-04-11 17:56:33.755 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: onCreate 1
2019-04-11 17:56:33.757 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: onCreateView 0
2019-04-11 17:56:33.773 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: onCreateView 1
2019-04-11 17:56:34.334 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: onDestroyView 3
2019-04-11 17:56:34.339 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: onDestroyView 4
2019-04-11 17:56:36.117 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: setUserVisibleHint -1 false
2019-04-11 17:56:36.118 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: setUserVisibleHint -1 false
2019-04-11 17:56:36.118 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: setUserVisibleHint 0 false
2019-04-11 17:56:36.118 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: setUserVisibleHint -1 true
2019-04-11 17:56:36.119 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: onCreate 2
2019-04-11 17:56:36.119 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: onCreate 3
2019-04-11 17:56:36.121 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: onCreateView 2
2019-04-11 17:56:36.135 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: onCreateView 3
2019-04-11 17:56:36.499 22031-22031/com.nanhuaqq.lazyfragment I/LazyLoadFragment: onDestroyView 0