【 ViewPager 】

ViewPager 如其名所述,是负责翻页的一个 View。准确说是一个 ViewGroup,包含多个 View 页,在手指横向滑动屏幕时,其负责对 View 进行切换。为了生成这些 View 页,需要提供一个 PagerAdapter 来进行和数据绑定以及生成最终的 View 页。

【 PagerAdapter 】

PageAdapter 是 ViewPager 的支持者,ViewPager 将调用它来取得所需显示的页,而 PageAdapter 也会在数据变化时,通知 ViewPager。这个类也是FragmentPagerAdapter 以及 FragmentStatePagerAdapter 的基类。如果继承自该类,至少需要实现 instantiateItem(), destroyItem(), getCount() 以及 isViewFromObject()。

  • getItemPosition()

    • 该函数用以返回给定对象的位置,给定对象是由 instantiateItem() 的返回值。
    • 在 ViewPager.dataSetChanged() 中将对该函数的返回值进行判断,以决定是否最终触发 PagerAdapter.instantiateItem() 函数。
    • 在 PagerAdapter 中的实现是直接传回 POSITION_UNCHANGED。如果该函数不被重载,则会一直返回 POSITION_UNCHANGED,从而导致 ViewPager.dataSetChanged() 被调用时,认为不必触发 PagerAdapter.instantiateItem()。很多人因为没有重载该函数,而导致调用
       PagerAdapter.notifyDataSetChanged() 后,什么都没有发生。
  • instantiateItem()
    • 在每次 ViewPager 需要一个用以显示的 Object 的时候,该函数都会被 ViewPager.addNewItem() 调用。
  • notifyDataSetChanged()
    • 在数据集发生变化的时候,一般 Activity 会调用 PagerAdapter.notifyDataSetChanged(),以通知 PagerAdapter,而 PagerAdapter 则会通知在自己这里注册过的所有 DataSetObserver。其中之一就是在 ViewPager.setAdapter() 中注册过的 PageObserver。PageObserver 则进而调用 ViewPager.dataSetChanged(),从而导致 ViewPager 开始触发更新其内含 View 的操作。

【 FragmentPagerAdapter 】

FragmentPagerAdapter 继承自 PagerAdapter。相比通用的 PagerAdapter,该类更专注于每一页均为 Fragment 的情况。如文档所述,该类内的每一个生成的 Fragment 都将保存在内存之中,因此适用于那些相对静态的页,数量也比较少的那种;如果需要处理有很多页,并且数据动态性较大、占用内存较多的情况,应该使用FragmentStatePagerAdapter。FragmentPagerAdapter 重载实现了几个必须的函数,因此来自 PagerAdapter 的函数,我们只需要实现 getCount(),即可。且,由于 FragmentPagerAdapter.instantiateItem() 的实现中,调用了一个新增的虚函数 getItem(),因此,我们还至少需要实现一个 getItem()。因此,总体上来说,相对于继承自 PagerAdapter,更方便一些。
  • getItem()

    • 该类中新增的一个虚函数。函数的目的为生成新的 Fragment 对象。重载该函数时需要注意这一点。在需要时,该函数将被 instantiateItem() 所调用。
    • 如果需要向 Fragment 对象传递相对静态的数据时,我们一般通过 Fragment.setArguments() 来进行,这部分代码应当放到 getItem()。它们只会在新生成 Fragment 对象时执行一遍。
    • 如果需要在生成 Fragment 对象后,将数据集里面一些动态的数据传递给该 Fragment,那么,这部分代码不适合放到 getItem() 中。因为当数据集发生变化时,往往对应的 Fragment 已经生成,如果传递数据部分代码放到了 getItem() 中,这部分代码将不会被调用。这也是为什么很多人发现调用 PagerAdapter.notifyDataSetChanged() 后,getItem() 没有被调用的一个原因。
  • instantiateItem()
    • 函数中判断一下要生成的 Fragment 是否已经生成过了,如果生成过了,就使用旧的,旧的将被 Fragment.attach();如果没有,就调用 getItem() 生成一个新的新的对象将被 FragmentTransation.add()
    • FragmentPagerAdapter 会将所有生成的 Fragment 对象通过 FragmentManager 保存起来备用,以后需要该 Fragment 时,都会从 FragmentManager 读取,而不会再次调用 getItem() 方法
    • 如果需要在生成 Fragment 对象后,将数据集中的一些数据传递给该 Fragment,这部分代码应该放到这个函数的重载里。在我们继承的子类中,重载该函数,并调用 FragmentPagerAdapter.instantiateItem() 取得该函数返回 Fragment 对象,然后,我们该 Fragment 对象中对应的方法,将数据传递过去,然后返回该对象。
    • 否则,如果将这部分传递数据的代码放到 getItem()中,在 PagerAdapter.notifyDataSetChanged() 后,这部分数据设置代码将不会被调用。
  • destroyItem()
    • 该函数被调用后,会对 Fragment 进行 FragmentTransaction.detach()。这里不是 remove(),只是 detach(),因此 Fragment 还在 FragmentManager 管理中,Fragment 所占用的资源不会被释放。

【 FragmentStatePagerAdapter 】

FragmentStatePagerAdapter 和前面的 FragmentPagerAdapter 一样,是继承子 PagerAdapter。但是,和 FragmentPagerAdapter 不一样的是,正如其类名中的 'State' 所表明的含义一样,该 PagerAdapter 的实现将只保留当前页面,当页面离开视线后,就会被消除,释放其资源;而在页面需要显示时,生成新的页面(就像 ListView 的实现一样)。这么实现的好处就是当拥有大量的页面时,不必在内存中占用大量的内存。
  • getItem()

    • 一个该类中新增的虚函数。
    • 函数的目的为生成新的 Fragment 对象。
    • Fragment.setArguments() 这种只会在新建 Fragment 时执行一次的参数传递代码,可以放在这里。
    • 由于 FragmentStatePagerAdapter.instantiateItem() 在大多数情况下,都将调用 getItem() 来生成新的对象,因此如果在该函数中放置与数据集相关的 setter 代码,基本上都可以在 instantiateItem() 被调用时执行,但这和设计意图不符。毕竟还有部分可能是不会调用 getItem() 的。因此这部分代码应该放到 instantiateItem() 中。
  • instantiateItem()
    • 除非碰到 FragmentManager 刚好从 SavedState 中恢复了对应的 Fragment 的情况外,该函数将会调用 getItem() 函数,生成新的 Fragment 对象。新的对象将被 FragmentTransaction.add()。
    • FragmentStatePagerAdapter 就是通过这种方式,每次都创建一个新的 Fragment,而在不用后就立刻释放其资源,来达到节省内存占用的目的的。
  • destroyItem()

38、FragmentStatePagerAdapter分页的更多相关文章

  1. Android实现网络音乐播放器

    本文是一个简单的音乐播放器 布局代码 <?xml version="1.0" encoding="utf-8"?> <RelativeLayo ...

  2. 套用JQuery EasyUI列表显示数据、分页、查询

    声明,本博客从csdn搬到cnblogs博客园了,以前的csdn不再更新,朋友们可以到这儿来找我的文章,更多的文章会发表,谢谢关注! 有时候闲的无聊,看到extjs那么肥大,真想把自己的项目改了,最近 ...

  3. springmvc+jpa实现分页的两种方式

    1.工具类 public final class QueryTool { public static PageRequest buildPageRequest(int pageNumber, int ...

  4. MVC分页

    http://www.cnblogs.com/iamlilinfeng/p/4075292.html 目录 一.Contrl与View数据传递(多表数据) 二.分页控件介绍 三.MVC源码说明 四.源 ...

  5. WORD学习之插入分页符

    我们在用Word编辑文档时,不可避免的需要对文档进行页面布局,才能使得文档看起来更加美观.有时候会使用到分页符,下面就简单介绍一下分页符 分页符 主要作用: 1.若要把两段分开在两页显示时,把光标定位 ...

  6. 重构MVC多条件+分页解决方案

    为支持MVC的验证,无刷新查询,EF,以及让代码可读性更强一点,所以就重构了下原来的解决方案. 这里就简单讲下使用方法吧: Model: 继承PagerBase: 1 public class Sea ...

  7. WinForm DataGridView分页功能

    WinForm 里面的DataGridView不像WebForm里面的GridView那样有自带的分页功能,需要自己写代码来实现分页,效果如下图: 分页控件  .CS: 1 using System; ...

  8. html中使用js+table 实现分页

    本文在html中利用js+table实现分页.主要思想是先对table中的所有数据隐藏,然后通过当前页面(currPageNum)来计算当前页要显示的行,并显示出来,首页.下一页.上一页.尾页都依此来 ...

  9. jQuery 滚动条 滚动到底部(下拉到底部) 加载数据(触发事件、处理逻辑)、分页加载数据

    1.针对浏览器整个窗口滚动 主要代码: <script type="text/javascript"> ; function GetProductListPageFun ...

随机推荐

  1. Hibernate逍遥游记-第9章 Hibernate的映射类型

    1. 2. <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate ...

  2. React使用rAF动画介绍

    一. <!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF ...

  3. Shell最多支持多少个参数

    本文转自:http://www.jb51.net/article/56548.htm   这篇文章主要介绍了Shell最多支持多少个参数?本文是对Shell最多可以输入多少个参数的一篇测试文章,需要的 ...

  4. kaili开启sshd服务

    使用xshell远程连接kali 2.0时要开启kaili上的sshd服务,具体方法如下: 命令: vim /etc/ssh/sshd_config # Package generated confi ...

  5. Filter过滤非法字符

    示例:定义一个Filter,用于用户发言中出现的“晕”字,即如果没有这个字则允许发言,如果有这个字则不允许发言并提示错误. CharForm.jsp <%@ page language=&quo ...

  6. UVa 1473 - Dome of Circus 三分

    把所有的点都映射到XOZ这个平面的第一象限内,则这个三维问题可以转化二维问题: 求一条直线,使所有点在这条直线的下方,直线与X轴和Z轴围成的三角形旋转形成的圆锥体积最小. 这样转化之后可以看出直线的临 ...

  7. PHP命名空间概念解析

    1. PHP中的命名空间是什么? 什么是命名空间?“从广义上来说,命名空间是一种封装事物的方法.在很多地方都可以见到这种抽象概念.例如,在操作系统中目录用来将相关文件分组,对于目录中的文件来说,它就扮 ...

  8. VB 语言学习笔记.

    暂时用到,学习学习. 变量声明 Dim 变量名 as 数据类型类型 Set 实例 = new 类名 自定义数据类型 Type 数据类型标识符 域名 As 数据类型; 域名 As 数据类型; 域名 As ...

  9. 字符设备 register_chrdev_region()、alloc_chrdev_region() 和 register_chrdev()

    1. 字符设备结构体 内核中所有已分配的字符设备编号都记录在一个名为 chrdevs 散列表里.该散列表中的每一个元素是一个 char_device_struct 结构,它的定义如下: static ...

  10. 使用 Oracle GoldenGate 在 Microsoft SQL Server 和 Oracle Database 之间复制事务

    使用 Oracle GoldenGate 在 Microsoft SQL Server 和 Oracle Database 之间复制事务 作者:Nikolay Manchev 分步构建一个跨这些平台的 ...