Подтвердить что ты не робот

Почему onAttach вызывается перед onCreate?

В жизненном цикле фрагментов метод onAttach() вызывается перед методом onCreate(). Я не могу обмотать голову вокруг этого. Зачем вам сначала прикреплять фрагмент?

4b9b3361

Ответ 1

TL; DR:

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

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

Слишком короткий; требуется больше:

Ответ находится в самом коде архетипа,

@Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnFragmentInteractionListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

Еще один пример можно найти в библиотеке Jake Wharton ActionBarSherlock.

Почему вы хотите использовать метод типа onCreate(), который имеет ту же цель в activity, service.

onCreate() предназначен для обработки проблем в отношении конкретного создания контекста. Не имеет смысла, если onCreate() используется для проверки состояния его контейнера.

Вторая причина, по которой я могу прийти, заключается в том, что фрагмент предназначен для независимой от активности. onAttach() предоставляет интерфейс для определения состояния/типа/(другой детали, относящейся к фрагменту) содержащейся активности с ссылку на фрагмент перед инициализацией фрагмента.

ИЗМЕНИТЬ

Активность существует независимо и, следовательно, имеет самоподдерживающийся жизненный цикл.

для фрагмента:

  • Независимые компоненты жизненного цикла (такие же, как и любые другие компоненты):

    • OnCreate()
    • OnStart()
    • onResume()
    • OnPause()
    • OnStop()
    • OnDestroy()
  • Компоненты, основанные на взаимодействии:

    • onAttach()
    • onCreateView()
    • onActivityCreated()
    • onDestroyView()
    • onDetach()

из документации:

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

Как только действие достигнет возобновленного состояния, вы можете свободно добавлять и удалите фрагменты в действие. Таким образом, только если возобновленное состояние может изменить жизненный цикл изменения фрагмента независимо друг от друга.

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

отвечая на другой вопрос, который возник в комментариях:

Внимание. Если вам нужен объект Context внутри вашего фрагмента, вы можете вызвать getActivity(). Однако будьте осторожны, чтобы вызвать getActivity() только тогда, когда фрагмент привязан к активности. Когда фрагмент еще не прикреплен или не был отсоединен в конце его жизненного цикла, getActivity() вернет значение null.

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

onCreate по определению отвечает за создание фрагмента. Рассмотрим случай ориентации, ваш фрагмент может быть: - использование разных макетов в разных ориентациях. - применяется только в портретной ориентации, а не в ландшафте - Используется только для таблиц и мобильных телефонов.

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

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

Ответ 2

Потому что onAttach() назначает хостинговую деятельность Fragment. Если бы он был вызван после onCreate(), тогда не было бы контекста для вашего фрагмента (getActivity() вернул бы null), и вы все равно ничего не смогли бы сделать в методе onCreate() без этого контекста.

Еще одна подходящая причина заключается в том, что жизненный цикл фрагмента похож на жизненный цикл Activity. В Activity.onAttach() активность привязана к ее родительскому объекту (окно). Аналогично в Fragment.onAttach() фрагмент привязывается к его родительскому объекту (активности), прежде чем любая другая инициализация будет выполнена.

Ответ 3

Это связано с сохранением фрагментов. Следующая документация setRetainInstance(boolean retain):

Если установлено, жизненный цикл фрагмента будет немного отличаться при воссоздании активности:

  • onDestroy() не будет вызываться (но onDetach() все равно будет, потому что фрагмент отсоединяется от его текущей активности).
  • onCreate (Bundle) не будет вызываться, так как фрагмент не создается повторно.
  • onAttach (Activity) и onActivityCreated (Bundle) все равно будут вызываться.

Взгляните на исходный код (android.support.v4.app.FragmentManager, v21):

void moveToState(Fragment f, 
                 int newState, 
                 int transit, 
                 int transitionStyle,
                 boolean keepActive) {
    ...
    f.onAttach(mActivity);
    if (!f.mCalled) {
        throw new SuperNotCalledException("Fragment " + f
                + " did not call through to super.onAttach()");
    }
    if (f.mParentFragment == null) {
        mActivity.onAttachFragment(f);
    }

    if (!f.mRetaining) {
        f.performCreate(f.mSavedFragmentState); // <- Here onCreate() will be called
    }
    ...
}

Пример

Случай 1: не сохраненный фрагмент или setRetainInstanceState (false)

Запускается приложение. Фрагмент добавляется динамически с помощью FragmentManager или раздувается из XML через setContentView().

onAttach() называется после Activity super.onCreate() call - активность уже инициализирована.

MainActivity﹕ call super.onCreate() before
MainActivity﹕ super.onCreate() returned
MainFragment﹕ onAttach() [email protected]
MainFragment﹕ onCreate() [email protected]

Изменена конфигурация. Активность воссоздает фрагменты из сохраненного состояния, фрагменты добавляются/прикрепляются изнутри Activity super.onCreate() call:

MainActivity﹕ call super.onCreate() before
MainFragment﹕ onAttach() [email protected]
MainFragment﹕ onCreate() [email protected]
MainActivity﹕ super.onCreate() returned

Случай 2: setRetainsInstanceState (true)

Запускается приложение. Фрагмент добавляется динамически с помощью FragmentManager или раздувается из XML через setContentView(). То же, что указано выше:

onAttach() называется после Activity super.onCreate() call - активность уже инициализирована.

MainActivity﹕ call super.onCreate() before
MainActivity﹕ super.onCreate() returned
MainFragment﹕ onAttach() [email protected]
MainFragment﹕ onCreate() [email protected]

Изменена конфигурация.

Фрагмент onCreate() не вызывается, но onAttach() по-прежнему называется - вам нужно знать, что активность хостинга изменилась. Но все же фрагмент уже создан, поэтому no onCreate().

MainActivity﹕ call super.onCreate() before
MainFragment﹕ onAttach() [email protected]
MainActivity﹕ super.onCreate() returned

Ответ 4

Две точки разработчика Android Сайт подсказывает, почему onAttach() вызывается до onCreate() в случае жизненного цикла фрагмента.

  • Фрагмент всегда должен быть встроен в действие. Теперь это означает, что для Fragment EXIST должна быть "живая" активность.
    Кроме того, когда вы добавляете фрагмент в качестве части вашего макета активности, он живет в ViewGroup внутри иерархии видов деятельности.

Итак, Fragment должен FIRST "прикрепить" себя к активности, чтобы определил свой собственный макет представления

  1. onCreate Вызывается для первоначального создания фрагмента.

Очевидно, что вы создадите что-то только тогда, когда его предварительное условие создания будет на месте (и предварительное условие - фрагмент A должен всегда быть встроен в действие и должен быть привязан к его активности)