架構示意圖
上圖一主Activity A內含兩個Fragmment A與B, 在 google 範例中設定了兩個 layout, 一個在 Handset下被啟用, 另一個則是在Tablet被啟用, layout內容如下:
但是當Fragment顯示資料需要依上層傳入的參數不同而有不同資料呈現時, 程式的設計上就變得需要有不同因應做法了, 為何會需要不同因應方式, 原因如下:
另外在 onStart() 呼叫須注意, 這與直覺似乎不同, 原以為應該是 ActivityA.onStart -> FargmentA.onStart -> FargmentB.onStart 但實際上是FargmentA.onStart -> FargmentB.onStart -> ActivityA.onStart 因此若有在 ActivityA.onStart 與Fragment動作就須注意了.
Fragment 模式整個啟動流程約如下
Handset模式, 為單一frame顯示, 放置於 res\layout
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fragment_container" android:layout_width="match_parent" android:layout_height="match_parent" />
Tablet模式, 為雙frame顯示, 放置於 res\layout-large
因此系統會自動依使用裝置來載入layout, 當為Tablet時系統不但載入雙Frame layout, 同時也會自動建立 FragmentA 與 FragmentB, 而若為Handset時則載入單Frame layout, 然後再由程式加入 FragmentA. 雖然這種模式蠻便利.<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment android:name="com.example.android.fragments.FragmentA" android:id="@+id/headlines_fragment" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" /> <fragment android:name="com.example.android.fragments.FragmentB" android:id="@+id/article_fragment" android:layout_weight="2" android:layout_width="0dp" android:layout_height="match_parent" /> </LinearLayout>
但是當Fragment顯示資料需要依上層傳入的參數不同而有不同資料呈現時, 程式的設計上就變得需要有不同因應做法了, 為何會需要不同因應方式, 原因如下:
通常 Fragment會藉由 getArguments()來取得上層傳入的參數, 這在單Frame運作模式下沒問題. 但是, 在雙Fragment就會有狀況, 因為 getArguments()的內容是在ActivityA程式內setArguments()來設定的
FragmentA a = new FragmentA(); a.setArguments(args);
但在雙Fragment啟動模式, 當ActivityA.setContentView()後, 兩個Fragment就由系統自動建立, 此時程式根本沒有setArguments(), 因此Fragment內就取不到上層參數了. 此一情況下, 若希望Fargment內, 不管是單/雙Frame模式下都採同一模式類似Acitvity使用習慣運作, 則建議如下
- 僅建立單一模式layout, 不在layout內指定Fargment.
- Fragment 均由程式內建立加入, 不由系統自動載入
- 自行判定是否呈現雙Fragment, 若是再加入其他Fragment.
這樣一來, Fragment 的動作就會一致, Fragment本身就不需要管自己是如何被建立, 該在何時機取得參數資料了.
另外在 onStart() 呼叫須注意, 這與直覺似乎不同, 原以為應該是 ActivityA.onStart -> FargmentA.onStart -> FargmentB.onStart 但實際上是FargmentA.onStart -> FargmentB.onStart -> ActivityA.onStart 因此若有在 ActivityA.onStart 與Fragment動作就須注意了.
Fragment 模式整個啟動流程約如下
ActivityA.onCreate
FargmentA.onCreate 到 onActivityCreated
FargmentB.onCreate 到 onActivityCreated
FargmentA.onStart
FargmentB.onStart
ActivityA.onStart
ActivityA.onResume
ActivityA.onResume
FargmentA.onResume
FargmentB.onResume