Fragment進階 - 基本用法

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里進行更詳細的介紹。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,556評論 25 708
  • 在各種Android項目中,我們不可避免要使用到Fragment,但很多地方其實我們只是習慣性或copy代碼來使用...
    HolenZhou閱讀 2,123評論 1 15
  • Fragment 描述: ??翻譯可以譯為:碎片、片段,Android 3.0開始引入fragments 的概念;...
    Lost_Robot閱讀 1,758評論 0 11
  • 從張琦屋里出來特意往311走,還真就看見汪書琪,對視了一眼。我覺得是我贏了。這小姑娘心亂了。 回泡崖和張金寶打籃球...
    自由的adam愛生活閱讀 454評論 0 0
  • 如果有一樣東西你必須學,他不可或缺,你學不會就無法繼續生活……那這樣東西不要任何人逼你,不用任何人向你灌輸“他太有...
    陳東Growth閱讀 308評論 0 0