Monday, July 9, 2012

Fragment筆記

撰寫日期︰2012/07/09 16:55
修改時間︰2015/10/26 14:07
修改次數︰5
一、前言
Android在3.0時就已經推出了Fragment(片斷)這個元件,可惜因為Android3.0以上的市占一直不高,因此一直沒有很完整的使用範例,但是因為最近我在用兼容套件,它能幫我們在Android2.x就使用Fragment,我也剛好用到,順便在這裡把我的學習心得記錄下來。

二、文章開始

1.淺談Fragment
Fragment,它屬於一個完整的Activity使用介面的其中一部份,想像一下,我們可以將多個fragments放在一個Activity底下,達到多區塊的程式能在一個或多個Activity間彼此靈活運用、互相溝通。(可以把它看成是一個子Activity,它們可以在很多個不同的Activity中同複使用)。

Fragment必需被崁在Activity裡面,它的生命週期也完全受到Activity的影響。什麼意思呢?假設今天Activity被Destroy()掉了,Fragment也會跟著被Destroy()掉。
然而,如果Activity運行中,你可以針對Activity裡的數個Fragment做個別獨立的控制,像是新增一個個的Fragment,甚至是移除掉它們。
當你執行fragment transaction時,你還能夠將你新增的Fragment添進back stack(背景堆疊,請見我2010年寫的文章)這個被Activity管理的機制中。每個back stack寫入時機皆發生在fragment transaction發生的時間點上,back stack允許使用者使用手機的返回鍵返回fragment transaction的狀態。

當你新增了一個fragment到你的Activity Layout的同時,它就被常駐進Activity裡ViewGroup的View階層中,它們還能夠自訂義應該要擁有怎麼樣的Layout。
你可以在Activity的Layout中去定義Fragment的擺放位置(使用<fragment>這個tag標籤),當然,也可以使用coding的方式,將Fragment放進Activity已存在的ViewGroup裡。然而,Fragment並不是一定需要成為Activity Layout的一部份的,因為Android也允許Fragment在一個無自屬UI狀態下,當成Activity的"隱性工作人員(invisible worker)"。酷吧!

2.設計原理
Android在3.0(API level 11)的時候介紹了這個Fragments元件,主要是用來支援在large screen(平板)裡多種動態及彈性的UI互動。因為平板的螢幕通常比手持裝置還要大,因此,也得到了許多能夠合併或在畫面中做改變的空間。Fragment因為能夠到幫你處理複雜的view階層(View hierarchy)運算,包括將一個Activity的layout傳至fragments中,因此你能在程式執行時期(Runtime)夠修改Activity的樣貌,也能夠讓Activity去管理並保留每一個fragment被改變的狀態,如同前面所說,存在back stack(背景堆疊)中。

提了那麼多,我在這裡做點假設。想像一下,有一隻APP可以在畫面的左邊顯示文章列表,右側則是顯示文章的內容,這2個都是fragment組成,而且還同時存在一個Activity中,酷吧?
每一個fragment都擁有各自的生命週期回呼函式(lifecycle callback),而且也能處理他們各自輸入事件,因此,fragment跟一般的Activity(一頁拿來讀文章列表,另一個Activity拿來讀內容)是很不一樣的。看看底下的圖1就知道了。
圖1. 此範例說明了如何在一個平板的Activity中,使用2個UI模組,但又能在手持裝置中分開使用。

你應該將每個Fragment模組化,並且讓它們能在Activity中重複使用。因為每個Fragment都定義了自己的layout、操作行為和自己的生命週期回呼函式。然而,因為你可以在多個Activity中去使用單一個Fragment,你就必須去設計得讓它們是能被重複使用的,並且盡量避免設計從A fragment直接手動存取B fragment。這件事很重要,因為一個被模組化的fragment能夠允許你在不同的螢幕中去做不同的排列組合。
當你的APP是設計給平板和手持裝置使用時,你就能利用你能使用的螢幕空間,去做最好且客製化的畫面呈現優化。舉例來說,手持裝置也許需要將多個fragment分散成一個一個的UI畫面,並讓它們存在各自的Activity中。但是因為你用了fragment,當你在用平板尺寸開發時,你就能崁進2個Fragments,然而,手持裝置卻因為空間不足,因此無法讓2個Fragments並存。所以手持裝置的Activity A只能放文章列表,Activity B則是放文章內容。也因為用了Fragment,這隻APP就能在手持和平板上共存,並且相容得很好。

3.建立一個Fragment
要建立一個Fragment,你必須繼承Fragment(或者繼承Fragment的子類別)。Fragment類別的程式碼看起來跟Activity很像,它擁有和Activity雷同的call back(回呼函式),像是onCreate()、onStart()、onPause()和onStop()。事實上,如果你要將你已經開發的APP轉移植到fragment中,你只要將這些code從你Activity的callback函式轉放到各自的fragment回呼函式中就可以了。

在使用Fragment時,通常你會需要實作至少3個生命週期回呼函式,它們是︰

onCreate() - 這個回呼函式是系統在建立Fragment時會呼叫的函式,你應該在這個回呼函式中初始化一些必要的元件,好讓fragment之後在pause或stopped、resumed時能使用。
onCreateView() - 系統會在要畫fragment的使用介面的第1時間去呼叫這個回呼函式。如果你有自訂義的view,你必須在這個回呼函式中return 一個自訂義的view(而且必須回傳為root),當然,如果Fragment沒有自己的View,你就回傳null吧!
onPaue() - 當使用者要離開時,系統會呼叫它。當你要儲存什麼值時,就在這個時機去儲存吧!

大部份的APP應該實作至少上述3種回呼函式。但是其實每個Fragment都有更多的回呼函式是你應該要去處理的。等等還會提到。

三、其它

官方文檔已將Fragment翻譯成中本版,
前往閱讀。