Замена фрагментов и изменение ориентации

Я разрабатываю приложение для Android, ориентированное на устройства 2.x и 3.0, и поэтому я использую 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 

Соответствующий код onCreateView из SearchFormFragment вызывает вызов, и я возвращаю действительный вид:

 @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 и изменениям состояния действительно не хватает.

Solutions Collecting From Web of "Замена фрагментов и изменение ориентации"

Не создавайте SearchFormFragment в XML. Вместо этого у вас есть пустой FrameLayout который вы заполняете в Activity.onCreate() не добавляя его в задний стек. Таким образом, Activity будет удерживать текущий Fragment вместо того, чтобы пытаться добавить тот, который указан в XML.

Кроме того, использование AsyncLoader может быть лучшим подходом, см. http://code.google.com/p/android/issues/detail?id=14944

После битвы с этим в течение многих часов я наконец получил его. Проблема заключается не в настройке или так, как мы называем класс фрагментов вообще. Это связано с неправильным сообщением, отображаемым на экране. Если у вас есть чек для контейнера, который является нулевым в вашем onCreateView () в вашем классе Ftagment, вы получите сообщение «неспособное раздуть фрагмент», а не контейнер – это нулевое сообщение. Итак, не проверяйте нулевой контейнер в своем onCreateView (). Поэтому убедитесь, что ваш 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)); } 

Для справочных целей: Мы смогли решить очень похожую проблему, добавив android:id к нашему фрагменту, созданному в XML.

Это очень важное условие для обеспечения безотказного вращения упоминается только как примечание в документации :

Примечание. Для каждого фрагмента требуется уникальный идентификатор, который система может использовать для восстановления фрагмента, если операция перезапускается (и которую вы можете использовать для захвата фрагмента для выполнения транзакций, например удаления).