Fragment进阶 - 基本用法

作者: 梦想编织者灬小楠 | 来源:发表于2016-10-17 13:42 被阅读1032次

    Fragment API文档
    (需要翻墙)

    本文内容

    • Fragment生命周期
    • Fragment创建步骤
    • Fragment静态加载
    • Fragment动态加载

    1. Fragment生命周期

    (下图为Steve Pomeroy制作的完整的Fragment生命周期图

    image.png

    注意点:

    1. Fragment以XML的方式静态加载时,最先会调用onInflate的方法(调用时机:Fragment所关联的Activity在执行setContentView时)。

    2. onInflate有两个重载的方法:

      • onInflate(Context context, AttributeSet attrs, Bundle savedInstanceState)(推荐使用)

      • onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState)(已废弃,不推荐被外部类调用)

    3. onAttach也有两个重载的方法:

      • onAttach(Context context)(推荐使用)

      • onAttach(Activity activity)(已废弃,不推荐被外部类调用)


    2. Fragment的创建步骤(最简单的方式)

    1.创建XML视图(供Fragment进行管理)

    fragment_xml.png

    2.创建Fragment

    fragment.png

    通过这两步我们的Fragment已经创建完毕了,接下来就是使用了。


    3. Fragment静态加载

    静态加载是指以XML的方式进行加载。(Activity和对应布局,如下图所示)

    main.png

    在fragment标签中需要添加name属性来指定你想添加的Fragment。

    接下来我们跑一下程序,界面就加载出来了。

    app.png

    接下来,给各位踩一下“静态加载Fragment”可能出现的坑。

    我们的fragment在xml中是这样写的,运行没有问题。

    <fragment
        android:id="@+id/content_fragment"
        android:name="com.sina.example.fragmentdemo.fragment.ContentFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
    

    但如果android:id这个属性忘记写的话就要遭殃了(事例如下)...

    <fragment
        android:name="com.sina.example.fragmentdemo.fragment.ContentFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
    

    我们去掉android:id属性跑下程序,结果程序崩了...,检查崩溃日志后得到了两条关键日志信息:

    ......
    Caused by: android.view.InflateException: Binary XML file line #6: Error inflating class fragment
    ......
    Caused by: java.lang.IllegalArgumentException: Binary XML file line #6: Must specify unique android:id, android:tag, or have a parent with an id for com.sina.example.fragmentdemo.fragment.ContentFragment
    

    第1条信息:告诉我们在Fragment填充布局的时候出错了。

    第2条信息:告诉我们解决这个问题的办法:必须指定android:id或android:tag或给我们的fragment的父容器一个id(解决办法如下图所示)。

    solve_error.png

    紧接着,我们用Hierarchy Viewer分析一下图层,说明一种现象。

    (1). 打开视图后,我们最先看到的是视图树的根View - DecorView(PhoneWindow的内部类)

    viewer.png

    (2). 顺着视图树向后看,我们看到一个id/content的视图容器.

    viewer2.png

    我们在Activity中setContentView就是向这个视图容器(android.R.id.content)中添加布局的。
    下方分支是ActionBar的相关布局,如果将标题栏去掉,你会发现下方的分支消失了。

    (3). 最后,可以看到我们自己写的布局文件

    viewer3.png
    • id/rl_main:是我们赋给Acitivity布局文件根布局的id值。

    • id/content_fragment:是我们赋给fragment的id值(但视图中却变成了RelativeLayout)

    • AppCompatImageView:我们的ImageView,未赋Id值。

    细心观察,我们会发现Fragment的id值赋给的了它所管理视图的最外层布局(RelativeLayout)。经过测试,发现不止id值,其他属性也赋值给了最外层布局(赋值是指对RelativeLayout没有的属性进行添加,已有的属性进行刷新)。

    结论:静态加载Fragment时,Fragment在XML设置的属性将赋值给它所管理视图的最外层布局。

    最后,看下如何在Activity中找到我们的Fragment。

    FragmentManager里有提供了“两种方法”查找我们的Fragment:

    • findFragmentById(@IdRes int id) : 通过id查找Fragment。(查找过程:第一次查找会从FragmentManager所管理的所有Fragment里查找,如果找不到,则会从关联过这个id的回退栈的所有Fragment里查找。如过找到则返回这个指定id的Fragment,否则返回null。)

    • findFragmentByTag(String tag):通过Tag查找Fragment。(查找过程:类比id的查找过程)

    看下上一步,我们Fragment的id值已经赋给了它所管理视图的最外层布局了,我们试下还能不能找到这个Fragment。

    fragment.png
    • 我们通过查找id的方式找到了我们的Fragment(ContentFragment)

    • 同一个id(R.id.content_fragment)以不同的方式查找得到了两个不同的对象

      • findViewById的方式我们得到的是Fragment的视图容器RelativeLayout。
      • findFragmentById的方式我们得到的是Fragment的实例ContentFragment。

    4. Fragment动态加载

    activity.png

    步骤:

    1. 在Activity的XML布局文件中添加一个FrameLayout视图容器(用于存放Fragment被添加后Fragment所管理的视图)。
    2. 在Activity中调用一个链式方法完成Fragment的动态添加。
      • getSupportFragmentManager() : 获取Fragment管理器(需要support.v4包)
      • beginTransaction() : 使Fragment管理器开启一个事务
      • add(R.id.fl-main, new ContentFragment(), null) : 在事务中进行一个添加操作,将目标Fragment添加到我们在步骤1中提供好的视图容器(R.id.fl_main)中 ,该Fragment的tag设为null。
      • commit() : 提交事务到主线程执行添加操作。

    PS:使用getSupportFragmentManager() 需要导入support.v4包,用来对Android3.0以下的版本进行兼容,不需要向下兼容可以考虑用 getFragmentManager()

    最后,跑一下程序,我们的界面就显示出来了。

    app.png

    接着,我们用Hierarchy Viewer查看一下图层,看下是不是我们所想象的。

    viewer4.png

    果然,Fragment中的布局完全装进了fl-main这个视图容器里,说明实例也已经被添加了。

    这里仅仅是介绍Fragment最简单的动态加载,后面小编会在FragmentTransaction里进行更详细的介绍。

    相关文章

      网友评论

      本文标题:Fragment进阶 - 基本用法

      本文链接:https://www.haomeiwen.com/subject/zejbyttx.html