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等),借此机会好好看下源码,欢迎留言。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏何俊林

如何进行网络视频截图/获取视频的缩略图

小编导读:获取视频的缩略图,截图正在播放的视频某一帧,是在音视频开发中,常遇到的问题。本文是主要用于点播中截图视频,同时还可以获取点播视频的缩略图进行显示,留下...

1.1K7
来自专栏木宛城主

探索MVP(Model-View-Presenter)设计模式在SharePoint平台下的实现

对于SharePoint Developers来说,往往会过多的去关注SharePoint平台和工具,而把设计模式和代码的可测试性放在了一个较低的优先级。这并...

2027
来自专栏bboysoul

linux 服务器带宽测试脚本ZBench

很郁闷,今天我的vultr服务器的ip被ban了,无奈只能换服务器,今天给大家推荐一个vps的带宽测速脚本ZBench可以一键测试你的服务器到国内和国外的速度

3842
来自专栏Android先生

RxJava2 实战知识梳理(2) - 计算一段时间内数据的平均值

今天,我们继续跟着 RxJava-Android-Samples 的脚步,一起看一下RxJava2在实战当中的应用,在这个项目中,第二个的例子的描述如下...

934
来自专栏图像识别与深度学习

《Android》Lesson16-Fragment

1646
来自专栏项勇

[Android笔记8]使用Zxing实现二维码扫描

2496
来自专栏Android小菜鸡

Android Touch事件传递机制

  Touch事件的传递机制与生活贴近,从父布局开始一步一步的向下分发事件。分发事件时调用boolean dispatchTouchEvent(MotionEv...

1953
来自专栏AI-vell

黑科技:程序员如何打造属于自己的分体键盘

为了不要这么纠结,就自己diy一个咯,正好有台3D打印机(又一个装B神器,你值得拥有,O(∩_∩)O哈哈~),全部外壳自己打印,控制板用Arduino Leon...

9908
来自专栏Flutter入门到实战

Android适配全面总结(三)----ROM适配

版权声明:本文为博主原创文章(部分引用他人博文,已加上引用说明),未经博主允许不得转载。https://www.jianshu.com/p/f9c67a4b90...

2841
来自专栏Android 开发者

在 Android O 上用到 MediaStyle 的提醒功能

3862

扫码关注云+社区

领取腾讯云代金券