Sự khác biệt giữa onCreateView và onViewCreate trong Fragment


118

Sự khác biệt cơ bản giữa hai phương pháp này là gì? Khi tôi tạo TextView, tôi có nên sử dụng cái này thay cho cái kia để đạt hiệu suất không?

Chỉnh sửa: Sự khác biệt so với

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

Tôi đã thêm một chỉnh sửa để giải thích sự nhầm lẫn của tôi. Nếu một phương pháp xuất hiện ngay sau phương pháp kia, tại sao lại có hai? Không thể thực hiện tất cả việc tạo chế độ xem trong một phương pháp như ở trên?
Smith

7
Nếu bạn phải google và đoán, có thể có những phương pháp được đặt tên rất tệ.
Balázs Németh

Câu trả lời:


85

Chúng tôi phải đối mặt với một số sự cố khi khởi tạo chế độ xem trong onCreateView.

Bạn nên phóng to bố cục của mình trong onCreateViewnhưng không nên khởi tạo các dạng xem khác bằng cách sử dụng findViewByIdtrong onCreateView.

Bởi vì đôi khi chế độ xem không được khởi tạo đúng cách. Vì vậy, luôn sử dụng findViewByIdtrong onViewCreated(khi chế độ xem được tạo hoàn toàn) và nó cũng chuyển chế độ xem dưới dạng tham số.

onViewCreated là đảm bảo rằng chế độ xem được tạo đầy đủ.

Tài liệu android onViewCreate

Được gọi ngay sau khi onCreateView( android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle) quay trở lại, nhưng trước khi bất kỳ trạng thái đã lưu nào được khôi phục trong dạng xem. Điều này cho phép các lớp con có cơ hội tự khởi tạo khi chúng biết hệ thống phân cấp chế độ xem của chúng đã được tạo hoàn toàn. Tuy nhiên, hệ thống phân cấp khung nhìn của phân mảnh không được gắn với cha mẹ của nó tại thời điểm này.


4
Cảm ơn. Tôi cũng phải đối mặt với vấn đề này và đã sử dụng thành phần. post(...) để đợi cho đến khi nó được hiển thị. Có thể sẽ làm cho findViewById và khởi tạo khác trong onViewCreated.
CoolMind

22
Văn bản đó được trích dẫn từ đâu? Tôi không thể tìm thấy nó trong tài liệu chính thức.
Daniel

Bạn có thể vui lòng đăng tài liệu tham khảo từ trang Nhà phát triển về tuyên bố được trích dẫn kèm theo đây không?
Namrata Bagerwal

4
Điều này không thực sự chính xác. Bạn có thể tìm thấy một chế độ xem trong onCreateView, nhưng chỉ sau khi bạn đã thổi phồng nó và chỉ từ chế độ xem bạn đã thổi phồng. Fragment.findViewById () không an toàn, nhưng View.findViewById () an toàn nếu bạn đã tăng chế độ xem phân mảnh.
colintheshots

46

onViewCreatedđược gọi ngay sau onCreateView(phương thức bạn khởi tạo và tạo tất cả các đối tượng của mình, bao gồm cả của bạn TextView), vì vậy nó không phải là vấn đề về hiệu suất.

Từ trang web của nhà phát triển:

onViewCreate (View view, Bundle đã lưuInstanceState)

Được gọi ngay sau khi onCreateView (LayoutInflater, ViewGroup, Bundle) đã trở lại, nhưng trước khi bất kỳ trạng thái đã lưu nào được khôi phục trong chế độ xem. Điều này cho phép các lớp con có cơ hội tự khởi tạo khi chúng biết hệ thống phân cấp chế độ xem của chúng đã được tạo hoàn toàn. Tuy nhiên, hệ thống phân cấp khung nhìn của phân mảnh không được gắn với cha mẹ của nó tại thời điểm này.

Nguồn: Fragment # onViewCreate


28

Tốt hơn là thực hiện bất kỳ sự phân công các lần xem phụ nào cho các trường trong onViewCreated. Điều này là do khuôn khổ thực hiện kiểm tra rỗng tự động cho bạn để đảm bảo rằng phân cấp chế độ xem Fragment của bạn đã được tạo và thổi phồng (nếu sử dụng tệp bố cục XML) đúng cách.

Đoạn mã từ: 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
nó cũng tách bất kỳ logic khởi từ logic lạm phát nhìn thứ bậc / tạo
orangemako

1
Điều này thật thú vị, bạn có bất kỳ nguồn bổ sung nào về lý do tại sao cách tiếp cận này tốt hơn không? Điều đó có nghĩa là mọi phương thức onCreateView chỉ nên bao gồm một "return perfater.inflate (R.layout.layout_file, container, false);" và onviewcrated nên có tất cả các phương thức "findViewById"? Điều này tạo ra hiệu suất tăng nào? Nó sẽ làm cho quá trình chuyển đổi nhanh hơn?
android_student

Để trả lời câu hỏi đầu tiên của bạn, onCreateViewđược sử dụng để tạo phân cấp chế độ xem của phân mảnh. Điều này có thể thông qua lạm phát XML hoặc tạo động (tức là tạo các khung nhìn Java theo chương trình). Vì vậy, bạn có thể không gọi inflategì cả. Nhưng bạn nên trả lại một số chế độ xem gốc nếu phân đoạn cần có phần tử giao diện người dùng. Nếu không thì trả lại null.
orangemako,

Không có sự tăng hiệu suất nào cả. Nhìn vào FragmentManagermã và đoạn mã performCreateViewgọi onCreateView github.com/android/platform_frameworks_base/blob/… , bạn được đảm bảo một số điều sau cho cuộc onViewCreatedgọi lại vòng đời:
orangemako

1. Hệ thống phân cấp chế độ xem sẽ được gắn vào vùng chứa nếu phân đoạn đã được thêm động vào hoạt động mẹ của nó. 2. Bạn có thể thực hiện tra cứu chế độ xem một cách an toàn mà không cần lo lắng về NPE. 3. Tôi không quen thuộc với các hoạt ảnh, nhưng quá trình chuyển đổi phân mảnh đã được bắt đầu (tức là, được gửi đến hàng đợi thông báo chuỗi giao diện người dùng).
orangemako,

13

onCreateViewtrả về chế độ xem tăng cao. OnViewCreatedđược gọi ngay sau onCreateViewvà get có tham số là chế độ xem được thổi phồng. Loại trả lại của nó làvoid


1
Tôi đã thêm một chỉnh sửa để giải thích sự nhầm lẫn của tôi. Nếu một phương pháp xuất hiện ngay sau phương pháp kia, tại sao lại có hai? Không thể thực hiện tất cả việc tạo chế độ xem trong một phương pháp như ở trên?
Smith

3
onCreateView sẽ trở lại nhanh chóng. Ví dụ: OnViewCreate có thể được sử dụng để thực hiện các công cụ khởi tạo. Như tôi đã nói, onViewCreate có tham số là View mà bạn đã tăng lên bên trong onCreateView. Vì vậy, bạn có thể tránh getViewcuộc gọi
Blackbelt

8

onCreateView()là Fragment tương đương với các onCreate()Hoạt động và chạy trong quá trình tạo Chế độ xem.
onViewCreated()chạy sau khi Chế độ xem đã được tạo.

should I use one over the other for performance? KHÔNG . Không có bằng chứng về việc tăng hiệu suất.

Thực ra cũng có một onCreate()phương thức trong Fragment, nhưng nó hiếm khi được sử dụng (tôi không bao giờ sử dụng nó, cũng như không tìm thấy một trường hợp sử dụng nào tốt cho nó).

Tôi luôn sử dụng onCreateView()trong Fragment để thay thế cho onCreate().
Và tôi hài lòng với điều đó.


2
@npace, tại sao? Tôi cũng nghĩ onCreateViewlà tương đương với Activity's onCreate.
CoolMind

2
@CoolMind Chà, nPace không hoàn toàn sai, vì cũng có một onCreate()phương thức trong Framents. Nhưng nó không bao giờ được sử dụng (hoặc, ít nhất, tôi không bao giờ sử dụng nó). Tôi luôn sử dụng onCreateView()trong Fragment để thay thế.
Phantômaxx

1
@Rotwang, đồng ý với bạn! Một số hướng dẫn sử dụng onCreate để đặt setHasOptionsMenu (true), nhưng tôi nghĩ nó sẽ tốt hơn trong onCreateView hoặc onViewCreate.
CoolMind

1
@CoolMind Tôi hoàn toàn đồng ý. Có lẽ tôi đã dùng sai từ trong câu trả lời của mình.
Phantômaxx

1
@Rotwang, bạn nói đúng. Khi tôi sử dụng các mảnh lần đầu tiên, tôi cũng không biết tại sao onCreate không được sử dụng.
CoolMind

4

Tài liệuFragment.onCreateView() hiện cho biết:

Bạn chỉ nên tăng cường bố cục trong phương pháp này và di chuyển logic hoạt động trên View được trả về thành onViewCreate (View, Bundle).

Không cần chúng tôi hiểu tại sao; chúng ta chỉ cần làm như tài liệu nói, nhưng sẽ rất thú vị nếu biết tại sao đề xuất này tồn tại. Dự đoán tốt nhất của tôi là tách rời mối quan tâm , nhưng IMHO điều này làm cho nó phức tạp hơn một chút so với nó.


Nếu lý do là tách quan tâm, thì tại sao con Hoạt động thổi phồng bố trí của nó trong setContentView()trong onCreate()?
Minh Nghĩa

@ MinhNghĩa Điểm tốt. Câu trả lời cho những câu hỏi đó có thể chỉ đơn giản là nó được thiết kế bởi một lập trình viên khác có suy nghĩ khác (các mảnh vỡ được giới thiệu vài năm sau khi chúng ta có Android lần đầu tiên), nhưng ai biết được.
Peppe LG

2

Lý do chính mà tôi sẽ sử dụng onViewCreatedlà vì nó tách bất kỳ logic khởi tạo nào khỏi logic lạm phát / tạo phân cấp chế độ xem sẽ đi trong onViewCreate. Tất cả các đặc điểm hiệu suất khác trông giống nhau.


2

Tôi nghĩ sự khác biệt chính giữa những điều này là khi bạn sử dụng kotlin.in onCreateView () Mỗi khi bạn muốn truy cập để xem trong tệp xml của mình, bạn nên sử dụng findViewById nhưng trong onViewCreate, bạn có thể chỉ cần truy cập vào chế độ xem của mình bằng cách gọi id của nó .


Điều này có thực sự đúng? Tôi nhận được null cho chế độ xem nếu tôi chỉ sử dụng id trong mã theo một trong hai cách. Tôi cần luôn sử dụng findViewById.
Jim Leask,

1
Không có nó không .. xem onCreate instantiates xem, onviewcreated được gọi sau khi oncreateview và các quốc gia trước khi lưu được khôi phục ... đó là hơn một vấn đề thời gian trong vòng đời của mảnh
me_

1

onCreateView được sử dụng trong phân mảnh để tạo bố cục và thổi phồng chế độ xem. onViewCreate được sử dụng để tham chiếu chế độ xem được tạo bởi phương thức trên. Cuối cùng, đó là một thực tiễn tốt để xác định trình nghe hành động trong onActivityCreate.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.