Tôi nên gọi super.initState ở cuối hoặc ở đầu?


10

Tôi bối rối không biết nên gọi super.initSate()ở đâu? Trong một số ví dụ mã, nó được gọi ở đầu và ở các mã khác ở cuối. Có sự khác biệt?

Tôi đã cố gắng google nó nhưng không tìm thấy bất kỳ lời giải thích nào về vị trí của chức năng gọi này.

Điều nào là đúng?

void initState() {
  super.initState();    
  //DO OTHER STUFF
}

hoặc là

void initState() {    
  //DO OTHER STUFF
  super.initState();    
}

Câu trả lời:


4

Nó cũng quan trọng đối với mixins (và vì điều đó đối với bạn )

Đó là một mô hình trong khung Flutter để gọi siêu phương thức khi ghi đè các phương thức vòng đời trong a State. Đây là lý do tại sao thậm chí deactivatecó một mustCallSuperchú thích .
Ngoài ra , một số người mixinmong đợi rằng bạn gọi siêu phương thức của các phương thức vòng đời đó tại một điểm cụ thể trong hàm.

Điều này có nghĩa là bạn nên làm theo tài liệu và gọi super.dispose vào cuốidispose phương thức của bạn vì mixins Statetrong khung mong đợi rằng đây là trường hợp.
Ví dụ: TickerProviderStateMixinkhẳng định ở cuối:SingleTickerProviderStateMixin super.dispose

Tất cả các Vé phải [..] được xử lý trước khi gọi super.dispose ().

Một ví dụ khác: AutomaticKeepAliveMixinthực thi logic trong initStatedispose.

Phần kết luận

Bắt đầu initStatevớisuper.initStatekết thúc disposevớisuper.dispose nếu bạn muốn ở bên dễ dàng và an toàn khi thêm mixins vào State.
Hơn nữa, hãy làm theo tài liệu cho các phương thức vòng đời khác (bất kỳ phương thức nào bạn ghi đè lên State) bởi vì khung sẽ mong đợi bạn gọi các siêu phương thức như được mô tả trong tài liệu.

Vì vậy, sau đây là những gì bạn nên làm:

void initState() {
  super.initState();    
  //DO OTHER STUFF
}

Tuy nhiên, nó không thực sự quan trọng State, điều mà tôi sẽ giải thích trong phần sau và thậm chí cho mixins, nó chỉ quan trọng đối với các xác nhận đánh giá từ những gì tôi có thể tìm thấy - vì vậy nó sẽ không ảnh hưởng đến ứng dụng sản xuất của bạn.

Nó không quan trọng State

Tôi nghĩ rằng hai câu trả lời trước của Pablo BarreraCopsOnRoadsai lệch vì sự thật của vấn đề là nó thực sự không quan trọng và bạn không cần phải tìm đâu xa.

Các hành động duy nhất super.initStatesuper.disposethực hiện trong Statechính lớp đó là các xác nhận và vì assert-statements chỉ được đánh giá trong chế độ gỡ lỗi , nên hoàn toàn không quan trọng khi xây dựng ứng dụng của bạn, tức là trong chế độ sản xuất.


Sau đây, tôi sẽ hướng dẫn bạn làm gì super.initStatesuper.disposelàm gì State, đó là tất cả các mã sẽ được thực thi khi bạn không có thêm mixin nào.

initState

Chúng ta hãy xem chính xác mã nào được thực thi trong super.initState( nguồn ) đầu tiên :

@protected
@mustCallSuper
void initState() {
  assert(_debugLifecycleState == _StateLifecycle.created);
}

Như bạn có thể thấy, chỉ có một xác nhận vòng đời và mục đích của nó là để đảm bảo rằng widget của bạn hoạt động chính xác. Vì vậy, miễn là bạn gọi super.initState một nơi nào đó của riêng initStatebạn, bạn sẽ thấy AssertionErrornếu tiện ích của bạn không hoạt động như dự định. Sẽ không có vấn đề gì nếu bạn thực hiện một số hành động trước bởi vì điều assertnày chỉ có nghĩa là báo cáo rằng có gì đó trong mã của bạn là sai và bạn sẽ thấy điều đó ngay cả khi bạn gọi super.initStatevào cuối phương thức của mình.

dispose

Các disposephương pháp tương tự ( nguồn ):

@protected
@mustCallSuper
void dispose() {
  assert(_debugLifecycleState == _StateLifecycle.ready);
  assert(() {
    _debugLifecycleState = _StateLifecycle.defunct;
    return true;
  }());
}

Như bạn có thể thấy, nó cũng chỉ chứa các xác nhận xử lý kiểm tra vòng đời gỡ lỗi . Cách thứ hai assertở đây là một mẹo hay vì nó đảm bảo rằng _debugLifecycleStatechỉ được thay đổi trong chế độ gỡ lỗi (vì các thay đổi assertchỉ được thực hiện trong chế độ gỡ lỗi).
Điều này có nghĩa là miễn là bạn gọi super.dispose một nơi nào đó trong phương thức của riêng bạn, bạn sẽ không mất bất kỳ giá trị nào nếu không có thêm các chức năng bổ sung.


1
Flutter docs không tốt lắm :( cảm ơn câu trả lời của bạn :)
CopsOnRoad

Cảm ơn lời giải thích của bạn, bạn cũng có thể giải thích, chỉ có một dòng trong initState()phương thức đó assert(...), vậy lợi ích của việc gọi super.initState()trong ứng dụng sản xuất là gì?
CopsOnRoad

1
Cảm ơn nhiều. Bây giờ nó có ý nghĩa! Vì vậy, tôi đoán là ở phía an toàn hơn và vì thực hành lập trình tốt, tốt nhất là giữ nó ở đầu mã.
K Vij

@creativecreatorormaybenot Điều đó có nghĩa là nhóm Flutter đã mất trí bằng cách đưa mustCallSupervào phương pháp đó hơn 2 năm kể từ khi Flutter ra đời. Lợi ích của việc đặt nó ở đó là gì thưa ông?
CopsOnRoad

@creativecreatorormaybenot Ngay cả khi nhóm đã tạo ra nó mixin, vẫn sẽ có một tuyên bố duy nhất trong initStateđó assert(...), vậy tầm quan trọng của việc gọi super.initState()ứng dụng sản xuất là gì?
CopsOnRoad

3

super.initState()phải luôn luôn là dòng đầu tiên trong initStatephương pháp của bạn .

Từ tài liệu:

initState (): Nếu bạn ghi đè lên điều này, hãy đảm bảo phương thức của bạn bắt đầu bằng một cuộc gọi đến super.initState ().


2

Như bạn có thể thấy trong các lớp từ khung công tác, bạn nên làm mọi thứ sau khi tiện ích được khởi tạo, nghĩa là sau super.initState().

Tôi trường hợp xử lý sẽ được logic theo cách khác, đầu tiên làm mọi thứ và sau đó gọi super.dispose().

@override
void initState() {
  super.initState();
  // DO STUFF
}

@override
void dispose() {
  // DO STUFF
  super.dispose();
}

Cám ơn. Nhưng tôi đã nhận thấy rằng trong một số ví dụ mã. nó được gọi ở cuối phương thức initState ...
K Vij

Đó là những gì tôi đã nói
Pablo Barrera

0

initState được gọi lên theo mặc định bất cứ khi nào một widget trạng thái mới được thêm vào cây widget. Bây giờ super.initState thực hiện cài đặt mặc định của lớp cơ sở của tiện ích con của bạn. Nếu bạn gọi bất cứ điều gì trước super.initState phụ thuộc vào lớp cơ sở thì điều này có thể gây ra sự cố. Đó là lý do tại sao bạn nên gọi initState theo cách này:

@override
void initState() {
  super.initState();
  // DO STUFF
}

Lý do là một chút thiếu sót bởi vì disposenó là ngược lại. Khung dự kiến ​​bạn sẽ gọi super.dispose vào cuối , nhưng khuyến nghị là chính xác.
creativecreatorormaybenot

Bởi vì nếu bạn gọi super.dispose trước khi loại bỏ những thứ khác thì các thành phần phụ thuộc vào lớp cơ sở của bạn có thể xung đột.
Anirudh Sharma
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.