需求如下:顶部UI(这里随便写的),一些标签(服务器给的,这里写死),切换标签展示不同内容,内容分页展示,要求可以下拉刷新(重要页面,没刷新太low了吧),刷新之后还停在当前标签下面,但是内容也要刷新,切换内容也会如此。(插插更健康:github源码有ScrollableLayout三段式悬浮布局,相同需求)。demo效果如下:

需求分析:看上去很简单的一个页面,但是做起来不一定那么顺畅,看我一步步分析。选用的控件毫无疑问是SwipeRefreshLayout+TabLayout+ViewPager+Fragment+FragmentStatePagerAdapter 。

分析1:由于标签数量length不确定(比较多),Fragment有预加载机制,如果使用默认的setOffscreenPageLimit提前加载下一个fragment,切换的时候导致看过的fragment被销毁/detach,再重新切换回去的话又得重新加载页面,请求api,体验很不好。如果使用setOffscreenPageLimit(length)预加载所有的fragment,更浪费资源,也不合理。所以需要使用Fragment的懒加载了,具体实现看后面的代码。

分析2:为什么不用FragmentPagerAdapter而是用FragmentStatePagerAdapter?

FragmentPagerAdapter类内的每一个生成的 Fragment 都将保存在内存之中,因此适用于那些相对静态的页,数量也比较少的那种。Fragment在切换的时候,不会销毁,而只是调用事务中的detach方法,我们只会把我们的Fragment的view销毁,而保留了以前的Fragment对象。所以通过这种方式创建的Fragment一直不会被销毁。

FragmentSatetePagerAdapter 的实现将只保留当前页面,当页面离开视线后,就会被消除,仅保留状态信息,释放其资源;而在页面需要显示时,恢复状态信息,这样更节省内存。

综上,根据需求选定FragmentStatePagerAdapter!

代码实现:

fragment懒加载基类:

import android.support.v4.app.Fragment;/*** Created by zrg on 2018/1/2.* Fragment的懒加载模式* 使用方法:* ***** 必须继承 FragmentPagerAdapter/FragmentStatePagerAdapter,才可以对setUserVisibleHint()调用* setUserVisibleHint() 设置Fragment的可见状态* getUserVisibleHint() 获取Fragment的可见状态* mIsVisible 是父类的成员变量,子类不需要重写* mIsprepared 子类需要在OnCreateView()中重写* mHasLoadedOnce 子类需要在lazyLoad()中重写* <p>* 接入步骤:* 1:继承BaseLazyFragment,实现lazyLoad()* 2:在onCreateView()中,添加以下代码:* mIsprepared = true;* lazyLoad();* 3:重写lazyLoad(){* if (!mIsprepared || !mIsVisible || mHasLoadedOnce) {* return;* }* mHasLoadedOnce = true;* //UI和业务逻辑* }* 4:拓展方法* stopLoad()://当视图已经对用户不可见并且加载过数据,* //如果需要在切换到其他页面时停止加载数据,可以覆写此方法* //此方法只在Fragment之间切换生效* visibleToUser(): 用户可看见当前的Fragment (神策埋点需要)* inVisibleToUser():用户看不见当前的Fragment,包含Fragment之间切换和跳转到Activity (神策埋点需要)*/
public abstract class BaseLazyFragment extends Fragment {/*** 判断当前的Fragment是否可见(相对于其他的Fragment)*/protected boolean mIsVisible;/*** 标志位,标志已经初始化完成*/protected boolean mIsprepared;/*** 是否已被加载过一次,第二次就不再去请求数据了*/protected boolean mHasLoadedOnce;@Overridepublic void setUserVisibleHint(boolean isVisibleToUser) {//设置Fragment的可见状态super.setUserVisibleHint(isVisibleToUser);if (getUserVisibleHint()) {//getUserVisibleHint获取Fragment可见状态mIsVisible = true;onVisible();} else {mIsVisible = false;onInvisible();}if (isResumed()) {onVisibilityChangedToUser(isVisibleToUser);}}/*** 可见*/protected void onVisible() {lazyLoad();}/*** 不可见*/protected void onInvisible() {stopLoad();}/*** 延迟加载* 子类必须重写此方法*/protected abstract void lazyLoad();/*** 当视图已经对用户不可见并且加载过数据,如果需要在切换到其他页面时停止加载数据,可以覆写此方法*/protected void stopLoad() {}//region 神策埋点需要,统计Fragement 可见时间@Overridepublic void onResume() {super.onResume();if (getUserVisibleHint()) {onVisibilityChangedToUser(true);}}@Overridepublic void onPause() {super.onPause();if (getUserVisibleHint()) {onVisibilityChangedToUser(false);}}/*** 当Fragment对用户的可见性发生了改变的时候就会回调此方法** @param isVisibleToUser true:用户能看见当前Fragment;false:用户看不见当前Fragment*/public void onVisibilityChangedToUser(boolean isVisibleToUser) {if (isVisibleToUser) {visibleToUser();} else {inVisibleToUser();}}protected void visibleToUser() {}protected void inVisibleToUser() {}//endregion}

ViewPagerActivity

public class ViewPagerActivity extends AppCompatActivity {private String[] TITLES = {"语文", "数学", "英语", "化学", "物理", "生物"};SwipeRefreshLayout mSwipeRefreshLayout;TabLayout mTabLayout;ViewPager mViewPager;private ViewPagerAdapter mAdapter;private int mCurrentIndex;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_view_pager);mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout);mTabLayout = (TabLayout) findViewById(R.id.tab_layout);mViewPager = (ViewPager) findViewById(R.id.view_pager);mAdapter = new ViewPagerAdapter(getSupportFragmentManager(), TITLES);mViewPager.setAdapter(mAdapter);mViewPager.setCurrentItem(0);mViewPager.setOffscreenPageLimit(TITLES.length - 1);mTabLayout.setupWithViewPager(mViewPager);final Handler handler = new Handler(Looper.getMainLooper());mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {@Overridepublic void onRefresh() {loadData();handler.postDelayed(new Runnable() {@Overridepublic void run() {mSwipeRefreshLayout.setRefreshing(false);}}, 1000);}});mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}@Overridepublic void onPageSelected(int position) {mCurrentIndex = position;}@Overridepublic void onPageScrollStateChanged(int state) {}});}private void loadData() {String[] titles = {"语文1", "数学1", "英语1", "化学1", "物理1", "生物1"};mAdapter.setTitles(titles);}
}

activity_view_pager

<android.support.v4.widget.SwipeRefreshLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/swipeRefreshLayout"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.hp.viewpagerdemo.ViewPagerActivity"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><ImageViewandroid:layout_width="match_parent"android:layout_height="120dp"android:src="@mipmap/ic_launcher"/><android.support.design.widget.TabLayoutandroid:id="@+id/tab_layout"style="@style/MyTablayoutStyle"android:layout_width="match_parent"android:layout_height="wrap_content"/><android.support.v4.view.ViewPagerandroid:id="@+id/view_pager"android:layout_width="match_parent"android:layout_height="match_parent"/></LinearLayout></android.support.v4.widget.SwipeRefreshLayout>
<!--Tablayout 设置属性-->
<style name="MyTablayoutStyle" parent="Widget.Design.TabLayout"><item name="tabIndicatorColor">#ff4f47</item><item name="tabSelectedTextColor">#4d4d4d</item><item name="tabBackground">@android:color/white</item><item name="tabTextAppearance">@style/MyTabLayoutTextAppearance</item>
</style><!--TabLayout 小标题-->
<style name="MyTabLayoutTextAppearance" parent="TextAppearance.AppCompat.Widget.ActionBar.Title"><item name="android:textColor">#999999</item><item name="android:textSize">14sp</item>
</style>

ViewPagerAdapter

public class ViewPagerAdapter extends FragmentStatePagerAdapter {private String[] mTitles;public ViewPagerAdapter(FragmentManager fm, String[] titles) {super(fm);mTitles = titles;}@Overridepublic Fragment getItem(int position) {EmptyFragment fragment = EmptyFragment.newInstance(mTitles[position]);Log.e("zrg", "getItem: 当前位置position=" + position);return fragment;}@Overridepublic int getCount() {return mTitles == null ? 0 : mTitles.length;}@Overridepublic Object instantiateItem(ViewGroup container, int position) {Log.e("zrg", "instantiateItem: 当前位置position=" + position);return super.instantiateItem(container, position);}@Overridepublic CharSequence getPageTitle(int position) {return mTitles == null ? "" : mTitles[position];}@Overridepublic int getItemPosition(Object object) {return POSITION_NONE;}public void setTitles(String[] titles) {mTitles = titles;notifyDataSetChanged();}
}

EmptyFragment

public class EmptyFragment extends BaseLazyFragment {private static final String ARG_TITLE = "arg_title";TextView mTvClick;private String mTitle;public EmptyFragment() {}public static EmptyFragment newInstance(String title) {EmptyFragment fragment = new EmptyFragment();Bundle bundle = new Bundle();bundle.putString(ARG_TITLE, title);fragment.setArguments(bundle);return fragment;}@Overridepublic void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);mTitle = getArguments().getString(ARG_TITLE);}@Nullable@Overridepublic View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View view = inflater.inflate(R.layout.fragment_empty, container, false);mTvClick = (TextView) view.findViewById(R.id.tv_click);mIsprepared = true;lazyLoad();return view;}@Overrideprotected void lazyLoad() {if (!mIsprepared || !mIsVisible || mHasLoadedOnce) {return;}mHasLoadedOnce = true;//UI和业务逻辑Log.e("zrg", "lazyLoad: 当前的fragment是:" + mTitle);mTvClick.setText(mTitle);}public String getTitle() {return mTitle;}
}

fragment_empty

<android.support.constraint.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:id="@+id/tv_click"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"/></android.support.constraint.ConstraintLayout>

注意事项

1、更新fragment不能使用重新设置adapter的方式,只能通过adapter.setTitle(args...)让adapter完成更新。

private void errorLoadData(){String[] titles = {"语文1", "数学1", "英语1", "化学1", "物理1", "生物1"};mAdapter = new ViewPagerAdapter(getSupportFragmentManager(), titles);mViewPager.setAdapter(mAdapter);mViewPager.setCurrentItem(mCurrentIndex);mViewPager.setOffscreenPageLimit(titles.length - 1);mTabLayout.setupWithViewPager(mViewPager);}

源码地址:https://github.com/zrg1215/ViewPagerRefreshDemo

源码包括ScrollableLayout三段式悬浮布局,实现方式大致相同,由于切换的时候需要知道当前fragment,源码里有 ,如果不了解ScrollableLayout的童鞋, 传送门。

ViewPager+Fragment刷新更新Fragment相关推荐

  1. TabLayout+ViewPager更新fragment的ui数据

    先看下这样一段代码 private String titles[] = new String[]{"今天", "这周", "这月", &qu ...

  2. android viewpager切换无法显示fragment问题

    为什么80%的码农都做不了架构师?>>>    具体是这样的,页面上需要显示一个底部切换的tab,在每个tab中需要显示一个顶部切换的tab,样子是这样的: 这里在切换下边的tab时 ...

  3. ViewPager PagerAdapter未更新视图

    我正在使用兼容性库中的ViewPager. 我已经巧妙地让它显示了几个我可以翻阅的视图. 但是,我很难弄清楚如何使用一组新视图更新ViewPager. 我已经尝试了各种各样的事情,比如调用mAdapt ...

  4. ViewPager的刷新

    ViewPager的刷新 最近有个需求涉及到viewpager的刷新问题,需求是这样的:一进入界面即发起数据请求,请求到数据后,根据数据的对象个数加载对应数目的fragment,并把相应的对象传递给f ...

  5. SwipeRefreshLayout+CoordinatorLayout+AppBarLayout+TabLayout+ViewPager+RecyclerView 刷新,不能滑动等问题

    使用SwipeRefreshLayout+CoordinatorLayout+AppBarLayout+TabLayout+ViewPager+Fragment+RecyclerView 实现首页悬浮 ...

  6. 你真的会用Fragment吗?Fragment复用的那些事儿

    如未特殊说明,本文中的知识点适用于 Activity 重建的时候,即: public void onCreate(Bundle savedInstanceState) {super.onCreate( ...

  7. android fragment概念,android Fragment相关概念简介

    Fragment fragment是一种控制器对象,activity可委派它完成一些任务,通常这些任务就是管理用户界面,受管理的用户界面可以是一整屏或是整屏的一部分, 管理用户界面的fragment又 ...

  8. Android Fragment中嵌套Fragment,不显示view

    原文链接:http://www.jianshu.com/p/e146698482f5 先看一段错误代码,这段代码写在一个 Fragment 中: private void initView(){mVi ...

  9. Fragment之一:Fragment入门

    参考自张泽华视频 Fragment是自Android3.0后引入的特性,主要用于在不同的屏幕尺寸中展现不同的内容. Fragment必须被嵌入Activity中使用,总是作为Activity的组成部分 ...

最新文章

  1. [na]出口选路pbr小实验视频
  2. 【转】复盘一次失败的技术面试后,我成功拿到了5个offer
  3. 全国计算机等级考试题库二级C操作题100套(第98套)
  4. 3 pyspark学习---sparkContext概述
  5. 【报告分享】2019年中国95后洞察报告.pdf(附下载链接)
  6. 我的Linux生涯之Mysql:Day01[Mysql基本使用]例
  7. 转:windows 蓝屏代码 .
  8. Infosys:印度信息技术巨头公司
  9. google搜索引擎使用方法
  10. Selenium下载与安装
  11. Unity ML-Agents 之 环境的搭建,以及的 demo 测试
  12. 基于轮廓系数来选择n_clusters(Kmeans聚类分析)
  13. PyTorch 实现 Skip-gram
  14. 【苦练基本功2】求最小公倍数
  15. Android 使用Gson解析json用法
  16. Linux应用(四)socket网络编程
  17. html导入外部webgl,【WebGL教程】Lesson 3 引入纹理以及简单的图像处理
  18. vue+electron 跨平台桌面应用开发实战教程
  19. 计算机在条形码的应用,条码应用系统的组成
  20. 在线中文摩尔斯密码加密解密工具

热门文章

  1. 程序员的“青春饭”能吃多久?IT行业的“年龄焦虑”该贩吗?
  2. 【网络工程师】<软考中级>网络互联与互联网
  3. 获取对话框当前cfont_MFC设置对话框、字体对话框、颜色对话框(转)
  4. java 复数_java怎么定义复数?
  5. 人工智能 | 自动驾驶与人工智能前沿研究报告(人才篇)
  6. android心跳包作用,Android开发Im总结-5:心跳包
  7. yota3墨水屏设置_YOTA3墨水屏“直通”技术取代旧“投射”功能,体验全面升级...
  8. base64图片在各种浏览器的兼容性处理
  9. co88 sap 实际结算_SAP生产订单实际成本计算
  10. 使用腾讯IP查询-判断IP归属地-Vic's blog