懒加载介绍
所谓的懒加载,其实也就是延迟加载,就是等到该页面的UI展示给用户时,再加载该页面的数据(从网络、数据库等),而不是依靠ViewPager预加载机制提前加载两三个,甚至更多页面的数据.这样可以提高所属Activity的初始化速度,也可以为用户节省流量.而这种懒加载的方式也已经/正在被诸多APP所采用.
但是通过ViewPager方法setOffscreenPageLimit(int limit)
的源码可以发现,ViewPager通过一定的逻辑判断来确保至少会预加载左右两侧相邻的1个页面,也就是说无法通过简单的配置做到懒加载的效果.
setUserVisibleHint(boolean isVisibleToUser)
,其中的参数isVisibleToUser
就是表示该Fragment的UI对于用户是否可见
基于以上原因,我们进行数据懒加载的时机需要满足两个条件
onCreateView()
方法执行完毕setUserVisibleHint(boolean isVisibleToUser)
方法返回true
所以在BaseFragment中用两个布尔型标记来记录这两个条件的状态.只有同时满足了,才能加载数据
<span style="color:#000000"><span style="color:#cccccc"><code class="language-java"><span style="color:#999999">//Fragment的View加载完毕的标记</span>
<span style="color:#cc99cd">private</span> <span style="color:#cc99cd">boolean</span> isViewCreated;
<span style="color:#999999">//Fragment对用户可见的标记</span>
<span style="color:#cc99cd">private</span> <span style="color:#cc99cd">boolean</span> isUIVisible;</code></span></span>
isViewCreated
标记
<span style="color:#000000"><span style="color:#cccccc"><code class="language-java">@Override
<span style="color:#cc99cd">public</span> <span style="color:#cc99cd">void</span> <span style="color:#f08d49">onViewCreated</span>(<span style="color:#f8c555">View</span> view, @Nullable <span style="color:#f8c555">Bundle</span> savedInstanceState) {
<span style="color:#cc99cd">super</span>.<span style="color:#f08d49">onViewCreated</span>(view, savedInstanceState);
isViewCreated <span style="color:#67cdcc">=</span> <span style="color:#f08d49">true</span>;
<span style="color:#f08d49">lazyLoad</span>();
}</code></span></span>
isUIVisible
标记
<span style="color:#000000"><span style="color:#cccccc"><code class="language-java">@Override
<span style="color:#cc99cd">public</span> <span style="color:#cc99cd">void</span> <span style="color:#f08d49">setUserVisibleHint</span>(<span style="color:#cc99cd">boolean</span> isVisibleToUser) {
<span style="color:#cc99cd">super</span>.<span style="color:#f08d49">setUserVisibleHint</span>(isVisibleToUser);
<span style="color:#999999">//isVisibleToUser这个boolean值表示:该Fragment的UI 用户是否可见</span>
<span style="color:#cc99cd">if</span> (isVisibleToUser) {
isUIVisible <span style="color:#67cdcc">=</span> <span style="color:#f08d49">true</span>;
<span style="color:#f08d49">lazyLoad</span>();
} <span style="color:#cc99cd">else</span> {
isUIVisible <span style="color:#67cdcc">=</span> <span style="color:#f08d49">false</span>;
}
}</code></span></span>
<span style="color:#000000"><span style="color:#cccccc"><code class="language-cpp"><span style="color:#cc99cd">private</span> <span style="color:#cc99cd">void</span> <span style="color:#f08d49">lazyLoad</span>() {
<span style="color:#999999">//这里进行双重标记判断,是因为setUserVisibleHint会多次回调,并且会在onCreateView执行前回调,必须确保onCreateView加载完毕且页面可见,才加载数据</span>
<span style="color:#cc99cd">if</span> (isViewCreated <span style="color:#67cdcc">&&</span> isUIVisible) {
<span style="color:#f08d49">loadData</span>();
<span style="color:#999999">//数据加载完毕,恢复标记,防止重复加载</span>
isViewCreated <span style="color:#67cdcc">=</span> <span style="color:#f08d49">false</span>;
isUIVisible <span style="color:#67cdcc">=</span> <span style="color:#f08d49">false</span>;
<span style="color:#f08d49">printLog</span>(mTextviewContent<span style="color:#67cdcc">+</span><span style="color:#7ec699">"可见,加载数据"</span>);
}
}</code></span></span>
loadData()
,具体加载数据的工作,交给子类去完成
<span style="color:#000000"><span style="color:#cccccc"><code class="language-csharp"><span style="color:#cc99cd">protected</span> <span style="color:#cc99cd">abstract</span> <span style="color:#cc99cd">void</span> <span style="color:#f08d49">loadData</span>();</code></span></span>
Android ViewPager中Fragment的生命周期&FragmentPageAdapter与FragmentStatePageAdapter对其的影响
- ViewPager使用细节,如何设置成每次只初始化当前的Fragment,其他的不初始化
相似点:
他们都无法保存视图,即在offScreenLimit之外的Fragment总是要被destroyView。
不同点:
最大的区别就是对于在offScreenLimit之外的Fragment,FragmentPagerAdapter会销毁试图,但Fragmnet不会detach,也就是Fragment还是在内存中的,当需要再次显示时他会createView,这意味着我们可以在Fragment对象中保存一些我们需要存储的信息,createView的时候做自己的选择。
而FragmentStatePagerAdapter就不同了,相同的情况下对于在offScreenLimit之外的Fragment,被destroyView只有还有detach,也就是此前的Fragment对象不复存在了,那么我们肯定不能在Fragment中保存必要的信息了,此时可以重写onSaveInstanceState来保存必要信息,并在onCreateView的时候重新拿出来用。FragmentStatePagerAdapter中为我们保存这些state是通过一个ArrayList来实现的,意味着他是记着Fragment的index作为key来保存或者取出的,
那么对于我们开发者来说,可以在此做个选择。在使用Viewpager中Fragment页面较少的情况可以选择FragmentPagerAdapter,这样代码会少几行,简单。