Сохранять объект фрагмента во время вращения
Я разработал приложение в Honeycomb, и я использую фрагменты.
Это мое приложение
- У меня есть Activity (Say A1) и в нем есть фрагмент
- Первоначально этот фрагмент удерживает объект в одном объекте фрагмента (F1)
- Затем в зависимости от действий пользователя он может измениться на другие объекты F2, F3....
Что моя проблема
Когда пользователь поворачивает устройство, активность воссоздается и делает F1 в качестве объекта фрагмента, хотя перед вращением он не был
What is the way to retain the fragment object while rotating?
Я использовал setRetainInstance(true);
, но для меня это не помогло
И я добавил фрагмент по коду в моей функции onCreate
, подобной этой
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
Fragment homeFragment = new Home();
fragmentTransaction.add(R.id.mainFragement, homeFragment);
fragmentTransaction.commit();
}
Ответы
Ответ 1
По умолчанию Android сохранит объекты фрагмента. В вашем коде вы устанавливаете homeFragment
в своей функции onCreate
. Именно поэтому всегда есть homeFragment
или fl
, что вы установили в onCreate
.
Потому что всякий раз, когда вы вращаетесь, функция onCreate выполняет и устанавливает объект фрагмента на первый
Итак, простое решение для вас - проверить, равен ли пакет savedInstanceState
null или нет, и установить объект фрагмента
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(null == savedInstanceState) {
// set you initial fragment object
}
}
Ответ 2
Вам нужно дать вашему фрагменту уникальный тег и проверить, уже ли этот фрагмент уже добавлен в вашу активность или нет.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String tag = "my_fragment";
FragmentManager fragmentManager = getFragmentManager();
if(fragmentManager.findFragmentByTag(tag) == null) {
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
Fragment homeFragment = new Home();
fragmentTransaction.add(R.id.mainFragement, homeFragment, tag);
fragmentTransaction.commit();
}
}
Проверка того, что savedInstanceState
равна null, не является безопасным способом проверить, установлен ли ваш фрагмент, - он будет работать в большинстве случаев, но в некоторых случаях (например, когда устройство находится на низкой памяти), Android может убить вашей деятельности, которая может разорвать ваше приложение.
Чтобы увидеть это в действии, отметьте "Не продолжать действия" в настройках разработки устройства (параметр доступен в Android 4.0+, не уверен в более ранних версиях). Когда вы открываете новое действие, ваше первое действие уничтожается. Когда вы вернетесь к нему (нажав назад), он будет создан снова, а savedInstanceState не будет нулевым. Тем не менее, ваш фрагмент больше не работает, и вы должны добавить его снова.
РЕДАКТИРОВАТЬ - показать исходный принцип, но с поддержкой SupportFragmentManager
public class ActivityAwesome extends AppCompatActivity
{
private final String TAG = getClass().getSimpleName();
private FragmentHome mHomeFragment;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
FragmentManager fragmentManager = getSupportFragmentManager();
Fragment fragment = fragmentManager.findFragmentByTag(TAG);
if(fragment == null)
{
// Create the detail fragment and add it to the activity using a fragment transaction.
mHomeFragment = new FragmentHome();
fragmentManager.beginTransaction()
.add(R.id.fragment_container, mHomeFragment, TAG)
.commit();
}
else
{
// get our old fragment back !
mHomeFragment = (FragmentHome)fragment;
}
}
}
это особенно полезно, если вы хотите манипулировать фрагментом (в данном случае mHomeFragment
) после вращения вашего устройства
Ответ 3
Используйте onAttachFragment()
в Activity
для переназначения объекта:
@Override
public void onAttachFragment(Fragment fragment) {
if (fragment instanceof MyFragment)
this.myFragment = (MyFragment) fragment;
}
Ответ 4
Я определил a Fragment
в макете действий, onSaveInstanceState
в Fragment
вызывает вызов, но savedInstanceState
Bundle
в фрагменте onCreatView
имеет значение null.
Причина в том, что у моего Fragment
не было идентификатора в XML:
android:id="@+id/compass_fragment" ...
Ответ 5
Вы можете просто установить свойство RetainInstance
внутри OnCreate
фрагмента класса.
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
RetainInstance = true;
}
Сохранить объект фрагмента при вращении
Ответ 6
просто измените @Ralf ответ, чтобы он был более динамичным, не нужно указывать определенный фрагмент для сохранения, но в случае, если вы захотите указать, это также возможно:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//set Home/Main/default fragment
changeFragmentTo(HomeFragment.newInstance(), FRAGMENT_TAG_HOME_FRAGMENT);
if (getCurrentFragment() != null) {
//if screen rotated retain Fragment
changeFragmentTo(getCurrentFragment(), getCurrentFragment().getTag());
}
}
private Fragment getCurrentFragment() {
//fl_main_container is FarmeLayout where I load my Fragments
return getSupportFragmentManager().findFragmentById(R.id
.fl_main_container);
}
/**
* changeFragmentTo(Fragment fragmentToLoad, String fragmentTag)
*
* @param fragmentToLoad : dataType > v4.app.Fragment :: the object of the fragment you want to load in form of MyFragment() or MyFragment().newInstance()
* @param fragmentTag : dataType > String :: a String which identify the "tag" of the fragment in form of "FRAGMENT_TAG_MY_FRAGMENT", Value must be stored in {@link models.MyConstants}
*/
public void changeFragmentTo(Fragment fragmentToLoad, String fragmentTag) {
if (getSupportFragmentManager().findFragmentByTag(fragmentTag) == null) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fl_main_container, fragmentToLoad, fragmentTag)
.setTransitionStyle(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.addToBackStack(fragmentTag)
.commit();
} else {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fl_main_container, fragmentToLoad, fragmentTag)
.setTransitionStyle(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.commit();
}
}
}