Использование пакета совместимости для целевой версии 2.2 с использованием фрагментов.
После перекодирования действия для использования фрагментов в приложении я не смог заставить работать изменение ориентации / управление состоянием, поэтому я создал небольшое тестовое приложение с одним FragmentActivity и одним фрагментом.
Журналы от изменения ориентации странные, с множественными вызовами фрагментов OnCreateView.
Очевидно, мне что-то не хватает - например, отсоединение фрагмента и его повторное присоединение, а не создание нового экземпляра, но я не вижу никакой документации, которая указала бы, где я ошибаюсь.
Кто-нибудь может пролить свет на то, что я делаю здесь не так, пожалуйста. Спасибо
Бревно выглядит следующим образом после изменения ориентации.
Initial creation
12-04 11:57:15.808: D/FragmentTest.FragmentTestActivity(3143): onCreate
12-04 11:57:15.945: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:57:16.081: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState null
Orientation Change 1
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): onSaveInstanceState
12-04 11:57:39.031: D/FragmentTest.FragmentTestActivity(3143): onCreate
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState not null
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:57:39.167: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState null
Orientation Change 2
12-04 11:58:32.162: D/FragmentTest.FragmentOne(3143): onSaveInstanceState
12-04 11:58:32.162: D/FragmentTest.FragmentOne(3143): onSaveInstanceState
12-04 11:58:32.361: D/FragmentTest.FragmentTestActivity(3143): onCreate
12-04 11:58:32.361: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:58:32.361: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState not null
12-04 11:58:32.361: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:58:32.361: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState not null
12-04 11:58:32.498: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:58:32.498: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState null
Основная деятельность (FragmentActivity)
public class FragmentTestActivity extends FragmentActivity {
/** Called when the activity is first created. */
private static final String TAG = "FragmentTest.FragmentTestActivity";
FragmentManager mFragmentManager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.d(TAG, "onCreate");
mFragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
FragmentOne fragment = new FragmentOne();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
}
И фрагмент
public class FragmentOne extends Fragment {
private static final String TAG = "FragmentTest.FragmentOne";
EditText mEditText;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d(TAG, "OnCreateView");
View v = inflater.inflate(R.layout.fragmentonelayout, container, false);
// Retrieve the text editor, and restore the last saved state if needed.
mEditText = (EditText)v.findViewById(R.id.editText1);
if (savedInstanceState != null) {
Log.d(TAG, "OnCreateView->SavedInstanceState not null");
mEditText.setText(savedInstanceState.getCharSequence("text"));
}
else {
Log.d(TAG,"OnCreateView->SavedInstanceState null");
}
return v;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.d(TAG, "FragmentOne.onSaveInstanceState");
// Remember the current text, to restore if we later restart.
outState.putCharSequence("text", mEditText.getText());
}
манифест
<uses-sdk android:minSdkVersion="8" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:label="@string/app_name"
android:name=".activities.FragmentTestActivity"
android:configChanges="orientation">
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
Ответы:
Вы накладываете свои фрагменты один на другой.
Когда происходит изменение конфигурации, старый фрагмент добавляется к новому действию при его воссоздании. Большую часть времени это сильная боль в тылу.
Вы можете остановить возникновение ошибок, используя тот же фрагмент, а не воссоздавая новый. Просто добавьте этот код:
Однако будьте осторожны: проблемы возникнут, если вы попытаетесь получить доступ к представлениям действий изнутри фрагмента, поскольку жизненные циклы будут незначительно изменяться. (Получить представления из родительского Activity из фрагмента непросто).
источник
"when the activity is destroyed, so are all fragments"
:? Поскольку"When the screen orientation changes, the system destroys and recreates the activity [...]"
.Чтобы процитировать эту книгу , «для обеспечения согласованного взаимодействия с пользователем Android сохраняет макет фрагмента и связанный задний стек при перезапуске Activity из-за изменения конфигурации». (стр.124)
И способ приблизиться к этому состоит в том, чтобы сначала проверить, был ли уже заполнен задний стек фрагментов, и создать новый экземпляр фрагмента, только если он еще не заполнен:
источник
Метод onCreate () вашего действия вызывается после изменения ориентации, как вы видели. Итак, не выполняйте FragmentTransaction, который добавляет фрагмент после изменения ориентации в вашей деятельности.
Фрагменты должны и должны быть неизменными.
источник
Вы можете
@Override
использовать FragmentActivityonSaveInstanceState()
. Убедитесь, что вы не вызывалиsuper.onSaveInstanceState()
метод.источник
Мы всегда должны пытаться предотвратить исключение нулевого указателя, поэтому мы должны сначала проверить в методе saveinstance информацию о пакете. для краткого объяснения, чтобы проверить эту ссылку в блоге
источник
Если вы просто делаете проект, то менеджер проекта говорит, что вам нужно добиться переключения экрана функции, но вы не хотите, чтобы экран переключался, загружая другой макет (можно создать макет и систему макетов-портов.
Вы автоматически определите состояние экрана, загрузите соответствующий макет), из-за необходимости повторно инициализировать действие или фрагмент, пользовательский интерфейс не очень хороший, а не непосредственно на переключателе экрана, я имею в виду? URL = YgNfP-VHY-Nuldi7YHTfNet3AtLdN-w__O3z1wLOnzr3wDjYo7X7PYdNyhw8R24ZE22xiKnydni7R0r35s2fOLcHOiLGYT9Qh_fjqtytJki & = & WD eqid = f258719e0001f24000000004585a1082
Предпосылка состоит в том, что ваш макет использует вес, как макет layout_weight, следующим образом:
Итак, мой подход заключается в том, что при переключении экрана не нужно загружать новый макет файла представления, изменять макет в динамических весах onConfigurationChanged, следующие шаги: 1 первый набор: AndroidManifest.xml в атрибуте активности: android: configChanges = "keyboardHidden | Ориентация | screenSize" Чтобы предотвратить переключение экрана, избегайте повторной загрузки, чтобы иметь возможность отслеживать в onConfigurationChanged 2 действие перезаписи или фрагмент в методе onConfigurationChanged.
источник
При изменении конфигурации платформа создаст для вас новый экземпляр фрагмента и добавит его в действие. Итак, вместо этого:
сделай это:
Обратите внимание, что фреймворк добавляет новый экземпляр FragmentOne при изменении ориентации, если вы не вызываете setRetainInstance (true), и в этом случае он добавит старый экземпляр FragmentOne.
источник