Fragment的延迟加载以及遇到的问题

问题

最近由于行情一波小牛,导致服务器带宽瓶颈。以前的客户端是一进入页面所有的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

你可能感兴趣的:(Fragment的延迟加载以及遇到的问题)