Різниця між onCreateView і onViewCreate у фрагменті


118

У чому суттєва відмінність цих двох методів? Коли я створю 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
Якщо вам доведеться google та здогадуєтесь, мабуть, погано названі методи.
Balázs Németh

Відповіді:


85

Ми стикаємося з деякими збоями, ініціалізуючи перегляд у onCreateView.

Ви повинні завищувати макет у, onCreateViewале не слід ініціалізувати інші представлення, використовуючи findViewByIdв onCreateView.

Тому що іноді перегляд неправильно ініціалізується. Тому завжди використовуйте findViewByIdв onViewCreated(коли перегляд повністю створено), і він також передає подання як параметр.

onViewCreated - переконайтесь, що представлення створено повністю.

onViewCreate Android Документація

Викликається одразу після повернення onCreateView( android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle), але до того, як збережений стан буде відновлено у перегляді. Це дає підкласам можливість ініціалізуватися, як тільки вони дізнаються, що їх ієрархія поглядів була повністю створена. Однак ієрархія перегляду фрагмента в цей момент не приєднана до його батьківського.


4
Дякую. Я також зіткнувся з цією проблемою і використав компонент. post(...) метод дочекатися його показу. Можливо, зроблять findViewById та ін. Ініціалізацію в onViewCreated.
CoolMind

22
Звідки цей текст цитується? Я не зміг його знайти в офіційній документації.
Даніель

Чи можете ви опублікувати посилання з сайту розробника на заяву, цитовану тут?
Намрата Багерваль

4
Це насправді не правильно. Ви можете знайти подання в onCreateView, але лише після того, як ви його надули, і лише з того виду, який ви вже надули. Fragment.findViewById () не є безпечним, але View.findViewById () безпечний, якщо ви вже завищили подання фрагмента.
знімки на колінці

46

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

З сайту розробника:

onViewCreate (Перегляд подання, Пакет збереженихInstanceState)

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

Джерело: фрагмент № onViewCreate


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);
}

6
вона також відокремлює будь-яку логіку ініціалізації від ієрархії поглядів на інфляцію / логіку створення
orangemako

1
Це цікаво, чи є у вас додаткові ресурси щодо того, чому такий підхід кращий? Чи означає це, що кожен метод onCreateView повинен складатися лише з "return inflater.inflate (R.layout.layout_file, container, false);" а у onviewcreate повинні бути всі методи "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і має параметр завищеного вигляду. Його тип повернення єvoid


1
Я додав редагування, щоб пояснити свою плутанину. Якщо один метод приходить відразу за іншим, чому існує два? Чи не можна створити все представлення в рамках одного методу, як описано вище?
Сміт

3
onCreateView повинен швидко повернутися. OnViewCreate, наприклад, може використовуватися для ініціалізації матеріалів. Як я вже сказав, onViewCreate має в якості параметра Перегляд, який ви надували всередині onCreateView. Тож ви можете уникнути getViewдзвінка
Блекбельт

8

onCreateView()- це еквівалент фрагмента onCreate()для діяльності та працює під час створення представлення.
onViewCreated()запускається після створення представлення.

should I use one over the other for performance? НІ . Немає доказів підвищення продуктивності.

Насправді onCreate()у Fragments також є метод, але він використовується рідконіколи його не використовую і не знаходжу для нього корисного випадку).

Я завжди використовую onCreateView()у Fragments як заміну onCreate().
І я задоволений цим.


2
@npace, чому? Я також думаю onCreateView, що це еквівалент діяльності onCreate.
CoolMind

2
@CoolMind Ну, nPace не зовсім помиляється, оскільки onCreate()метод є і у Framents. Але він ніколи не використовується (або, принаймні, я ніколи його не використовую). Я завжди використовую onCreateView()у Fragments як заміну.
Phantômaxx

1
@Rotwang, згоден з тобою! Деякі навчальні посібники використовують onCreate для встановлення setHasOptionsMenu (true), але я думаю, що це краще зробити в onCreateView або onViewCreate.
CoolMind

1
@CoolMind Я повністю згоден. Можливо, я використовував неправильні слова у своїй відповіді.
Phantômaxx

1
@Rotwang, ти правильно сказав. Коли я вперше використовував фрагменти, я також не знав, чому onCreate не використовується.
CoolMind

4

ДокументиFragment.onCreateView() наразі говорять:

Рекомендується лише надути макет у цьому методі та перемістити логіку, яка працює на поверненому представленні до onViewCreate (View, Bundle).

Не потрібно нам розуміти, чому; нам просто потрібно зробити так, як кажуть документи, але було б цікаво знати, чому ця рекомендація існує. Моя найкраща здогадка - це розділення проблем , але IMHO це робить трохи складнішим, ніж це має бути.


Якщо причиною є поділ відповідальності, то чому активність надути його розташування в setContentView()в onCreate()?
Minh Nghĩa

@ MinhNghĩa Хороший момент. Відповідь на ці запитання може бути просто тим, що його розробив інший програміст, який мислив по-різному (фрагменти були представлені через кілька років після того, як ми вперше отримали Android), але хто знає.
Peppe LG

2

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


2

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


Це справді правда? Я стає нульовим для перегляду, якщо я просто використовую ідентифікатор у коді будь-яким способом. Мені потрібно завжди використовувати findViewById.
Jim Leask

1
Ні, це не так. Oncreate view створює подання, onviewcreate викликається після oncreateview і до того, як збережені стани будуть відновлені ... це більше питання про терміни в життєвому циклі фрагмента
me_

1

onCreateView використовується в фрагменті для створення макета та надуття подання. onViewCreate використовується для посилання на представлення, створене вищевказаним методом. Нарешті, є хорошою практикою визначити слухача дій у програмі onActivityCreate.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.