[英]Replacing fragments and orientation change
我正在開發一個針對2.x和3.0設備的Android應用程序,因此我正在使用compatiblebilty API。 我在Android 2.0上測試。
我正在嘗試將顯示的片段替換為另一個片段(搜索結果與搜索結果一起),並且當顯示第二個(結果)片段時,我遇到了方向更改的崩潰。
基本上,我有一個活動,包括在布局xml中定義的片段
<fragment class="org.prevoz.android.search.SearchFormFragment"
android:id = "@+id/search_form_fragment"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent" />
第一個片段(SearchFormFragment)顯示為默認值。 當用戶點擊“搜索”按鈕時,我將SearchFormFragment替換為SearchResultsFragment,后者運行AsyncTask(這就是我想保留它的原因)
// Show the search results fragment
SearchResultsFragment newSearch = new SearchResultsFragment(from, to, when);
newSearch.setRetainInstance(true);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
transaction.replace(R.id.search_form_fragment, newSearch);
transaction.addToBackStack(null);
transaction.commit();
但是,當顯示SearchFormFragment並更改方向時,我的應用程序崩潰了
ERROR/AndroidRuntime(334): FATAL EXCEPTION: main
ERROR/AndroidRuntime(334): java.lang.RuntimeException: Unable to start activity ComponentInfo{org.prevoz.android/org.prevoz.android.search.MainActivity}: android.view.InflateException: Binary XML file line #13: Error inflating class fragment
ERROR/AndroidRuntime(334): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663)
ERROR/AndroidRuntime(334): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
ERROR/AndroidRuntime(334): at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3815)
ERROR/AndroidRuntime(334): at android.app.ActivityThread.access$2400(ActivityThread.java:125)
ERROR/AndroidRuntime(334): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2037)
ERROR/AndroidRuntime(334): at android.os.Handler.dispatchMessage(Handler.java:99)
ERROR/AndroidRuntime(334): at android.os.Looper.loop(Looper.java:123)
ERROR/AndroidRuntime(334): at android.app.ActivityThread.main(ActivityThread.java:4627)
ERROR/AndroidRuntime(334): at java.lang.reflect.Method.invokeNative(Native Method)
ERROR/AndroidRuntime(334): at java.lang.reflect.Method.invoke(Method.java:521)
ERROR/AndroidRuntime(334): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
ERROR/AndroidRuntime(334): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
ERROR/AndroidRuntime(334): at dalvik.system.NativeStart.main(Native Method)
ERROR/AndroidRuntime(334): Caused by: android.view.InflateException: Binary XML file line #13: Error inflating class fragment
ERROR/AndroidRuntime(334): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:582)
ERROR/AndroidRuntime(334): at android.view.LayoutInflater.rInflate(LayoutInflater.java:618)
ERROR/AndroidRuntime(334): at android.view.LayoutInflater.inflate(LayoutInflater.java:407)
ERROR/AndroidRuntime(334): at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
ERROR/AndroidRuntime(334): at android.view.LayoutInflater.inflate(LayoutInflater.java:276)
ERROR/AndroidRuntime(334): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:198)
ERROR/AndroidRuntime(334): at android.app.Activity.setContentView(Activity.java:1647)
ERROR/AndroidRuntime(334): at org.prevoz.android.search.MainActivity.onCreate(MainActivity.java:40)
ERROR/AndroidRuntime(334): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
ERROR/AndroidRuntime(334): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
ERROR/AndroidRuntime(334): ... 12 more
ERROR/AndroidRuntime(334): Caused by: java.lang.IllegalStateException: Fragment org.prevoz.android.search.SearchFormFragment did not create a view.
ERROR/AndroidRuntime(334): at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:281)
ERROR/AndroidRuntime(334): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:558)
ERROR/AndroidRuntime(334): ... 21 more
WARN/ActivityManager(59): Force finishing activity org.prevoz.android/.search.MainActivity
來自SearchFormFragment的相關onCreateView代碼會被調用,並返回一個有效的視圖:
@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState)
{
View newView = inflater.inflate(R.layout.search_form_frag, container, false);
return newView;
}
只有在顯示SearchResultsFragment時才會發生崩潰,如果顯示默認的SearchFormFragment,則更改正常。
那么如何通過方向改變保留第二個片段狀態呢? 關於API和狀態變化的文檔確實缺乏。
不要在XML中創建SearchFormFragment
。 而是有一個空的FrameLayout
,您可以在Activity.onCreate()
填充它而不將其添加到后台堆棧。 這樣, Activity
將保留當前的Fragment
而不是嘗試添加XML中指定的那個。
此外,使用AsyncLoader
可能是一種更好的方法,請參閱http://code.google.com/p/android/issues/detail?id=14944
出於參考原因:我們能夠通過在我們用XML創建的片段中添加一個android:id
來解決一個非常類似的問題。
支持無崩潰輪換的這一非常重要的前提條件僅作為文檔中的附注提及 :
注意:每個片段都需要一個唯一的標識符,如果重新啟動活動,系統可以使用該標識符來恢復片段(您可以使用它來捕獲片段以執行事務,例如刪除它)。
經過幾個小時的掙扎,我終於明白了。 問題不在於設置或我們調用Fragment類的方式。 它與屏幕上顯示的錯誤信息有關。 如果在Ftagment類的onCreateView()中檢查容器是否為null,則會得到“無法擴充片段”消息,而不是容器為空消息。 因此,不要在onCreateView()中檢查null容器。 因此,請確保您的onCreateView()看起來像這樣:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return(inflater.inflate(R.layout.title_layout, container, false));
}
而不是這樣的:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if(container == null){
return null;
}
return(inflater.inflate(R.layout.title_layout, container, false));
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.