Разница между onCreateView и onViewCreated во фрагменте

119

В чем принципиальная разница между этими двумя методами? Должен ли я использовать один элемент поверх другого для повышения производительности при создании TextView?

Изменить: в чем разница от

onCreateView() {
  root = some view
  View v = new View(some context);
  root.add(v);
  return root;
}


onViewCreated() {
  View v = new View(some context);
  getView().add(v);
}
кузнец
источник
Я добавил правку, чтобы объяснить свое замешательство. Если один метод приходит сразу за другим, почему их два? Разве невозможно создание всех представлений одним методом, как показано выше?
Смит
7
Если вам нужно погуглить и угадать, вероятно, существуют методы с плохими названиями.
Балаж Немет

Ответы:

85

Мы сталкиваемся с некоторыми сбоями при инициализации представления в onCreateView.

Вы должны раздуть свой макет, onCreateViewно не должны инициализировать другие представления, используя findViewByIdin onCreateView.

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

onViewCreated Убедитесь, что представление полностью создано.

onViewCreated Android Документация

Вызывается сразу после возврата onCreateView( android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle), но до восстановления какого-либо сохраненного состояния в представлении. Это дает подклассам возможность инициализировать себя, как только они узнают, что их иерархия представлений полностью создана. Однако на этом этапе иерархия представления фрагмента не привязана к его родительскому элементу.

Зар Э Ахмер
источник
4
Спасибо. Я тоже столкнулся с этой проблемой и использовал компонент. post(...), чтобы дождаться его отображения. Возможно сделает findViewById и прочую инициализацию в onViewCreated.
CoolMind
22
Откуда был процитирован этот текст? Я не нашел его в официальной документации.
Daniel
Не могли бы вы опубликовать ссылку с сайта разработчика на цитируемое здесь заявление?
Намрата Багерваль
4
На самом деле это не так. Вы можете найти представление в onCreateView, но только после того, как вы его увеличите, и только из того представления, которое вы уже создали. Fragment.findViewById () небезопасен, но View.findViewById () безопасен, если вы уже раздули представление фрагмента.
colintheshots
46

onViewCreatedвызывается сразу после onCreateView(метода, который вы инициализируете и создаете все свои объекты, включая ваш TextView), так что это не вопрос производительности.

С сайта разработчика:

onViewCreated (представление представления, пакет savedInstanceState)

Вызывается сразу после возврата onCreateView (LayoutInflater, ViewGroup, Bundle), но до восстановления любого сохраненного состояния в представлении. Это дает подклассам возможность инициализировать себя, как только они узнают, что их иерархия представлений полностью создана. Однако на этом этапе иерархия представления фрагмента не привязана к его родительскому элементу.

Источник: Фрагмент # onViewCreated

u3l
источник
28

Любое присвоение подвидов полям в onViewCreated. Это связано с тем, что фреймворк выполняет автоматическую нулевую проверку, чтобы убедиться, что иерархия представления вашего фрагмента была создана и увеличена (при использовании файла макета XML) должным образом.

Фрагмент кода из: FragmentManger.java

// This calls onCreateView()
f.mView = f.performCreateView(f.getLayoutInflater(f.mSavedFragmentState), null, f.mSavedFragmentState);

// Null check avoids possible NPEs in onViewCreated
// It's also safe to call getView() during or after onViewCreated()
if (f.mView != null) {
    f.mView.setSaveFromParentEnabled(false);
    if (f.mHidden) f.mView.setVisibility(View.GONE);
    f.onViewCreated(f.mView, f.mSavedFragmentState);
}
orangemako
источник
6
он также отделяет любую логику инициализации от логики инфляции / создания иерархии представлений
orangemako 06
1
Это интересно, есть ли у вас дополнительные ресурсы о том, почему этот подход лучше? Означает ли это, что каждый метод onCreateView должен состоять только из «return inflater.inflate (R.layout.layout_file, container, false)»; а onviewcreated должны иметь все методы findViewById? Какой прирост производительности это дает? Сделал бы переходы быстрее?
android_student
Чтобы ответить на ваш первый вопрос, onCreateViewиспользуется для создания иерархии представлений фрагмента. Это может быть через расширение XML или динамическое создание (т. Е. Создание представлений Java программным способом). Так что можно вообще не звонить inflate. Но вы должны вернуть какое-то родительское представление, если фрагмент должен иметь элемент пользовательского интерфейса. В противном случае вернитесь null.
orangemako
Никакого прироста производительности нет. Глядя на FragmentManagerкод фрагмента и для performCreateView, который вызывает onCreateView github.com/android/platform_frameworks_base/blob/… , вам гарантировано несколько вещей для onViewCreatedобратного вызова жизненного цикла:
orangemako
1. Иерархия представления будет прикреплена к контейнеру, если фрагмент был динамически добавлен в его родительскую операцию. 2. Вы можете безопасно выполнять поиск по просмотрам, не беспокоясь о NPE. 3. Я не так хорошо знаком с анимацией, но переход фрагмента уже был запущен (то есть отправлен в очередь сообщений потока пользовательского интерфейса).
orangemako
13

onCreateViewвозвращает увеличенный вид. OnViewCreatedвызывается сразу после onCreateViewи имеет параметр inflated view. Его возвращаемый типvoid

Черный пояс
источник
1
Я добавил правку, чтобы объяснить свое замешательство. Если один метод приходит сразу за другим, почему их два? Разве невозможно создание всех представлений одним методом, как показано выше?
Смит
3
onCreateView должен быстро вернуться. OnViewCreate можно использовать, например, для выполнения инициализации. Как я уже сказал, onViewCreated имеет в качестве параметра View, который вы раздули внутри onCreateView. Так что вы можете избежать getViewзвонка
Blackbelt
8

onCreateView()является эквивалентом фрагмента onCreate()для Activity и запускается во время создания представления.
onViewCreated()запускается после создания представления.

should I use one over the other for performance? Нет . Нет никаких свидетельств повышения производительности.

Во onCreate()Фрагментах тоже есть метод, но он используется редконикогда не использую его и не нахожу для него подходящего варианта).

Я всегда использую onCreateView()фрагменты в качестве замены onCreate().
И я доволен этим.

Phantômaxx
источник
2
@npace, почему? Я также считаю, что onCreateViewэто эквивалент Activity onCreate.
CoolMind
2
@CoolMind Что ж, nPace не совсем неправ, поскольку onCreate()во Framents тоже есть метод. Но он никогда не использовался (или, по крайней мере, я им никогда не пользуюсь). Я всегда использую onCreateView()фрагменты в качестве замены.
Phantômaxx,
1
@Rotwang, согласен с тобой! Некоторые учебники используют onCreate для установки setHasOptionsMenu (true), но я думаю, что лучше было бы использовать onCreateView или onViewCreated.
CoolMind 04
1
@CoolMind Я полностью согласен. Возможно, я использовал неправильные слова в своем ответе.
Phantômaxx,
1
@Rotwang, ты правильно сказал. Когда я впервые использовал фрагменты, я также не знал, почему не используется onCreate.
CoolMind
4

Документы наFragment.onCreateView() данный момент говорят:

В этом методе рекомендуется только раздуть макет и переместить логику, которая работает с возвращенным View, в onViewCreated (View, Bundle).

Нам не нужно понимать почему; нам просто нужно делать то, что написано в документации, но было бы интересно узнать, почему существует эта рекомендация. Мое лучшее предположение - разделение проблем , но ИМХО это делает его немного сложнее, чем должно быть.

Пеппе LG
источник
Если причина в разделении проблем, то почему Activity раздувает свой макет в setContentView()in onCreate()?
Минь Нгха,
@ MinhNghĩa Хорошее замечание. Ответом на эти вопросы может быть просто то, что он был разработан другим программистом, думающим иначе (фрагменты были представлены через несколько лет после того, как мы впервые получили Android), но кто знает.
Peppe LG,
2

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

AmeyaB
источник
2

Я думаю, что основное различие между ними заключается в том, что вы используете kotlin.in onCreateView () каждый раз, когда вы хотите получить доступ к просмотру в своем XML-файле, вы должны использовать findViewById, но в onViewCreated вы можете просто получить доступ к своему представлению, просто вызвав его идентификатор ,

Шахриар енаяты
источник
Это правда? Я получаю значение null для представления, если в любом случае просто использую идентификатор в коде. Мне всегда нужно использовать findViewById.
Джим Лиск
1
Нет, это не так ... oncreate view создает экземпляр представления, onviewcreated вызывается после oncreateview и до восстановления сохраненных состояний ... это скорее проблема времени в жизненном цикле фрагмента
me_
1

onCreateView используется во фрагменте для создания макета и расширения представления. onViewCreated используется для ссылки на представление, созданное указанным выше методом. Наконец, рекомендуется определить слушателя действий в onActivityCreated.

Салу Хадка
источник