Странная ошибка жизненного цикла фрагмента - PullRequest
13 голосов
/ 03 мая 2011

РЕДАКТИРОВАТЬ

Таким образом, кажется, что мой Fragment сохраняется в FragmentManager, который пытается его повторно инициализировать.Все еще не уверен, почему он не уничтожен с Activity.Что касается сообщения о загрузке, оно отображается, когда ListView не имеет установленного адаптера.Однако я устанавливаю элементы адаптера в onCreate и onResume, поэтому я не уверен, почему отображается этот экран загрузки.Все еще открыты для любых объяснений этого поведения

Оригинал

Я играю с фрагментами и заметил странную ошибку, которая появляется, когда я меняю ориентациюэкран.Эта ошибка не должна возникать, потому что все данные воссоздаются в onCreate при изменении ориентации экрана.Также фрагмент onResume() вызывается дважды после поворота.Вот мои шаги для создания ошибки и как отладчик воздействует на функции.

  • Activity: onCreate ()
  • Activity: onResume ()
  • Fragment: onResume()
  • Поворот экрана
  • Активность: onCreate ()
  • Активность: onResume ()
  • Фрагмент: onResume () (элементы являются нулевыми, даже если активность.onResume () устанавливает их)
  • Fragment: onResume () (элементы не равны NULL, почему это вызывается дважды?)

После нажатия на этот последний фрагмент onResumeна планшете отображается сообщение и значок «Загрузка ...» .Почему данные больше не отображаются в списке?Я подозреваю, что onCreate создает второй фрагмент.Первый фрагмент теряет свои данные из-за ориентации, разрушающей представления, второй фрагмент получает данные, а экран загрузки является первым фрагментом без элементов данных, а второй фрагмент скрыт.Я могу ошибатьсяПочему фрагменты не разрушаются при повороте экрана, как Activity?Пожалуйста, не критикуйте код, если он не решает эту конкретную проблему.На самом деле я не делаю приложение, я экспериментирую с функциональностью фрагментов.Спасибо!

Основная активность

private ArrayList<Object> items = new ArrayList<Object>();
private MyListFragment mylistFragment;

public MainActivity() {
    items.add("Hello");
    items.add("World");
    items.add("Goodbye");
}

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    FragmentManager fm = getFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();

    mylistFragment = new MyListFragment();
    mylistFragment.setItems(items);

    ft.add(R.id.container, mylistFragment);
    ft.commit();
}

@Override
public void onResume() {
    super.onResume();

    mylistFragment.setItems(items);
    mylistFragment.getListView().setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            Toast.makeText(MainActivity.this, ((TextView)view).getText(), Toast.LENGTH_LONG).show();
        }

    });
}

Фрагмент списка

private List<Object> items = null;
private Boolean isSet = false;

@Override
public void onResume() {
    super.onResume();
    if( !isSet && items != null) {
        setListAdapter(new ArrayAdapter<Object>(getActivity(), R.layout.item, items));
        isSet = true;
    }
}

public void setItems(List<Object> items) {
    this.items = items;
    if( this.isResumed() ) {
        setListAdapter(new ArrayAdapter<Object>(getActivity(), R.layout.item, items));
        isSet = true;
    } else {
        isSet = false;
    }
}

Ответы [ 3 ]

5 голосов
/ 03 мая 2011

FragmentManager автоматически создаст для меня Fragment. Однако данные внутри них должны быть повторно инициализированы. Поэтому мой код создавал второй фрагмент. Экран загрузки был из-за того, что у первого фрагмента больше не было адаптера элементов, а второй был скрыт. Какая головная боль, я почти думаю, что FragmentManager должен уничтожить Fragments, чтобы вы могли воссоздать их с данными, которые они хранят.

0 голосов
/ 14 мая 2014

Похоже, что использование FragmentActivity из библиотеки поддержки автоматически сохраняет и восстанавливает экземпляр.Поэтому выполняйте только ваши транзакции фрагментов, если savedInstanceState равно null.

Например, в ваших FragmentActivity onCreate() выполните следующие действия:

if(savedInstanceState == null){
       FragmentManager fragmentManager = getSupportFragmentManager();
       fragmentManager.beginTransaction()
       .replace(R.id.fragment_container, mFragment).commit(); //mFragment is your own defined fragment
}
0 голосов
/ 07 мая 2011

Я полагаю, что именно поэтому в различных демонстрациях с помощью Diane и других примеров Google ... у них обычно есть некоторый способ помочь инициализации с помощью статического метода ... и setArguments.

IIRC, средство создания фрагмента вызовет конструктор по умолчанию для создания, но знает только о заполнении соответствующими данными через setArguments.В примере на блоге по разработке Android ... идентификатор передавался из списка рассылки во фрагмент данных.После вызова setParams для фрагментаManager должна быть возможность его реанимировать.

Документация, кажется, немного разбросана по этому вопросу, и я хотел бы поступить правильно, поэтому, если у вас, ребята, есть отзывы, я был бы признателенэто.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...