在默認狀況下當發生橫豎屏切換時,當前Activity中的fragment都會經過Fragment.instantiate從新生成,該方法將使用默認的構造函數來生成相應的Fragment,因此若是沒有默認構造函數的話將會報錯,例如: java
class MyFragment { public MyFragment(int title, String message){ } public static final MyFragment newInstance(int title, String message) { MyFragment f = new MyFragment (int title, String message); return f; } }這時候當橫豎屏切換時因爲MyFragment沒有默認構造函數,將拋出java.lang.InstantiationException異常,正確的方式爲使用Bundle來進行參數傳遞修改以下:
class MyFragment { private static final String TITLE="title",MESSAGE="message"; private String title,message; public void onCreate(Bundle saveInstanceState){ title = getArguments().getString(TITLE); message = getArguments().getString(MESSAGE); } public static final MyFragment newInstance(int title, String message) { MyFragment f = new MyFragment (int title, String message); Bundle bdl = new Bundle(2); bdl.setString(TITLE,title); bdl.setString(MESSAGE,message); f.setArguments(bdl); return f; } }
經過這種方式建立的Fragment在橫豎屏切換時經過getArguments依然可以得到以前設置的數據,其原理是在FragmentActivity切換時會調用onRetainNonConfigurationInstance方法將FragmentManager中管理的全部Fragment及其狀態數據(其中就包括了這個設置的Bundle)保存在一個FragmentActivity.NonConfigurationInstances對象實例中,這樣在新的FragmentActivity啓動時在onCreate方法中可使用Activity.getLastNonConfigurationInstance()方法來獲取這個對象,而後經過FragmentManager.restoreAllState方法還原全部Fragment及其狀態,須要注意的是在這種狀況下可能會出現以前的Fragment沒有detach而處於活動狀態致使該Fragment的視圖生成,可能會形成兩個Fragment視圖重疊的狀況,在官方的Support.v4的例子中FragmentTabs.TabManager.addTab裏有一段檢查Fragment是否detach的代碼正是用於解決這個問題。 android
經過上面的處理基本是沒問題了,但由於默認狀況下橫豎屏切換後整個FragmentActivity會被銷燬並重建,全部Fragment中的成員變量也會丟失,但全部的Fragment狀態數據如上所述會被保留並還原,這個時候全部的視圖都會從新建立。 函數
解決方法一:在相應的Activity配置中加上android:configChanges="orientation|keyboardHidden"設置,這樣切換時就不會銷燬FragmentActivity,全部的Fragment的狀態及視圖也就會保持。 spa
解決方法二:在使用FragmentTransaction.add()方法添加fragment時設置第三個tag參數,隨後在還原時可經過FragmentManager.findFragmentByTag()方法找回還原的fragment. rest