android ViewPager+Fragment之懒加载
说说写这篇博客的背景吧,前两天去面试,问到一个问题说的是:比如我们首页,是有3个fragment构成的,并且要是实现作用可以滑,那么这个最好的选择就是ViewPager+fragment了,但是我们知道ViewPager+fragment是做预加载的,然而这种方法有一个坏处,当前页面和预加载页面都有大量的网络请求,可能就会比较慢,这样就会造成不好打体验。其实我们忽略的一个问题,Android的fragment里面已经帮我们提供了一个方法setUserVisibleHint。setUserVisibleHint()来显示与隐藏Fragment的。
我们看一下系统的代码:
- public void setUserVisibleHint(boolean isVisibleToUser) {
 - if (!mUserVisibleHint && isVisibleToUser && mState < STARTED) {
 - mFragmentManager.performPendingDeferredStart(this);
 - }
 - mUserVisibleHint = isVisibleToUser;
 - mDeferStart = !isVisibleToUser;
 - }
 
但是setUserVisibleHint优于onCreate调用,所以当onCreate调用完毕setUserVisibleHint就不会触发,这时需要在首个显示的fragment调用setUserVisibleHint方法。
所以我们在第一个Fragment创建成功之后,需要设置下下一个页面是否展示
- public void onActivityCreated(Bundle savedInstanceState) {
 - // TODO Auto-generated method stub
 - setUserVisibleHint(true);
 - super.onActivityCreated(savedInstanceState);
 - }
 
为了方便我们使用我们可以继承fragment重写一下setUserVisibleHint方法。
- public abstract class BasePageFragment extends Fragment {
 - protected boolean isViewInitiated;
 - protected boolean isVisibleToUser;
 - protected boolean isDataInitiated;
 - @Override
 - public void onCreate(Bundle savedInstanceState) {
 - super.onCreate(savedInstanceState);
 - }
 - @Override
 - public void onActivityCreated(Bundle savedInstanceState) {
 - super.onActivityCreated(savedInstanceState);
 - isViewInitiated = true;
 - prepareFetchData();
 - }
 - @Override
 - public void setUserVisibleHint(boolean isVisibleToUser) {
 - super.setUserVisibleHint(isVisibleToUser);
 - this.isVisibleToUser = isVisibleToUser;
 - prepareFetchData();
 - }
 - public abstract void fetchData();
 - public boolean prepareFetchData() {
 - return prepareFetchData(false);
 - }
 - public boolean prepareFetchData(boolean forceUpdate) {
 - if (isVisibleToUser && isViewInitiated && (!isDataInitiated || forceUpdate)) {
 - fetchData();
 - isDataInitiated = true;
 - return true;
 - }
 - return false;
 - }
 - }
 
说下这里关于prepareFetchData的判断逻辑:当前UI可见,并且fragment已经初始化完毕,如果网络数据未加载,那么请求数据,或者需要强制刷新页面,那么再去请求页面数据,这样就达到了本文开始需要的要求。
用的话也听方便的:
- public class PageFragment extends BasePageFragment {
 - public static PageFragment newInstance(String title){
 - PageFragment fragment = new PageFragment();
 - Bundle args = new Bundle();
 - args.putString("key_fragment_title", title);
 - fragment.setArguments(args);
 - return fragment;
 - }
 - private String title;
 - private TextView tv;
 - @Override
 - public void onCreate(Bundle savedInstanceState) {
 - super.onCreate(savedInstanceState);
 - title = getArguments().getString("key_fragment_title");
 - Trace.d(title + ":onCreate");
 - }
 - @Override
 - public void onResume() {
 - super.onResume();
 - Trace.d(title + ":onResume");
 - }
 - @Override
 - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
 - Trace.d(title + ":onCreateView");
 - tv = new TextView(getActivity());
 - return tv;
 - }
 - @Override
 - public void fetchData() {<pre code_snippet_id="1723966" snippet_file_name="blog_20160621_4_911600" name="code" class="html"> //这里是网络异步请求返回
 
- tv.setText(title); }}
 
}
通过setOffscreenPageLimit进行Fragment缓存
- public void setOffscreenPageLimit(int limit) {
 - if (limit < DEFAULT_OFFSCREEN_PAGES) {
 - Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to " +
 - DEFAULT_OFFSCREEN_PAGES);
 - limit = DEFAULT_OFFSCREEN_PAGES;
 - }
 - if (limit != mOffscreenPageLimit) {
 - mOffscreenPageLimit = limit;
 - populate();
 - }
 - }
 
好了,最近面试面到的比较坑的问题还蛮多(比如Intent底层实现,Looper底层算法,Ams等),借此机会好好看下源码,欢迎留言。
                    
                
                
            
        
浙公网安备 33010602011771号