ฉันควรเรียก super.initState ในตอนท้ายหรือตอนต้น?


10

ฉันสับสนว่าจะโทรไปที่super.initSate()ใด ในตัวอย่างรหัสบางอย่างมันถูกเรียกที่จุดเริ่มต้นและในตอนท้ายอื่น ๆ มีความแตกต่างหรือไม่?

ฉันได้ลอง google แล้ว แต่ยังไม่พบคำอธิบายใด ๆ เกี่ยวกับตำแหน่งของการเรียกใช้ฟังก์ชันนี้

อันไหนที่ถูก?

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

หรือ

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

คำตอบ:


4

มันสำคัญสำหรับmixins (และเพราะสิ่งนั้นสำหรับคุณเช่นกัน)

มันเป็นกระบวนทัศน์ในกรอบ Flutter Stateจะเรียกวิธีสุดเมื่อเอาชนะวิธีวงจรใน นี่คือเหตุผลที่แม้จะdeactivateมีคำอธิบายประกอบmustCallSuper
นอกจากนี้บางคนmixinคาดหวังว่าคุณจะเรียกวิธีการขั้นสูงของวิธีวงจรชีวิตเหล่านั้นที่จุดเฉพาะในฟังก์ชั่น

ซึ่งหมายความว่าคุณควรปฏิบัติตามเอกสารและเรียกใช้super.dispose เมื่อสิ้นสุดdisposeวิธีการของคุณเนื่องจากmixinอยู่Stateในกรอบงานที่คาดว่าเป็นกรณีนี้
ตัวอย่างเช่น: TickerProviderStateMixinและยืนยันในตอนท้าย:SingleTickerProviderStateMixin super.dispose

ทิกเกอร์ทั้งหมดต้อง [.. ] ถูกกำจัดก่อนโทร super.dispose ()

อีกตัวอย่างหนึ่ง: AutomaticKeepAliveMixinดำเนินการทางตรรกะในและinitStatedispose

ข้อสรุป

เริ่มต้นของคุณinitStateมีsuper.initStateและสิ้นสุดของคุณdisposeด้วยsuper.disposeถ้าคุณต้องการที่จะเป็นทางด้านความง่ายและปลอดภัยเพิ่มเพื่อคุณmixin นอกจากนี้ให้ทำตามเอกสารประกอบสำหรับวิธีการวงจรชีวิตอื่น ๆ (วิธีการใด ๆ ที่คุณเขียนทับ) เนื่องจากกรอบงานจะคาดหวังว่าคุณจะเรียกวิธีการขั้นสูงดังที่อธิบายไว้ในเอกสารประกอบState
State

ดังนั้นต่อไปนี้คือสิ่งที่คุณควรทำ:

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

แต่มันไม่ได้จริงๆเรื่องStateซึ่งผมจะอธิบายในต่อไปและแม้กระทั่งสำหรับ mixins ก็เพียงเรื่องสำหรับยืนยันการตัดสินจากสิ่งที่ฉันสามารถหา - ดังนั้นจึงจะไม่ส่งผลกระทบต่อการผลิตของคุณแอป

มันไม่สำคัญสำหรับ State

ฉันคิดว่าสองคำตอบก่อนหน้าจากPablo BarreraและCopsOnRoadกำลังทำให้เข้าใจผิดเพราะความจริงของเรื่องนี้คือมันไม่สำคัญและคุณไม่จำเป็นต้องมองไปไกล

การกระทำเดียวที่super.initStateและsuper.disposeใช้เวลาในStateชั้นเรียนเองยืนยันและตั้งแต่assert-statements มีการประเมินเฉพาะในโหมดการแก้ปัญหามันไม่ได้เรื่องที่ทั้งหมดเมื่อสร้างแอปของคุณเช่นในโหมดการผลิต


ในต่อไปนี้ผมจะแนะนำคุณผ่านสิ่งsuper.initStateและsuper.disposeทำในStateซึ่งเป็นรหัสที่จะได้รับการดำเนินการเมื่อคุณไม่มี mixins เพิ่มเติม

initState

ให้เราดูว่ารหัสใดถูกเรียกใช้ในsuper.initStateครั้งแรก (ที่มา ):

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

อย่างที่คุณเห็นมีเพียงวงจรการยืนยันและวัตถุประสงค์ของมันคือเพื่อให้แน่ใจว่าวิดเจ็ตของคุณทำงานอย่างถูกต้อง ดังนั้นตราบใดที่คุณโทรหาที่super.initState ใดที่หนึ่งด้วยตัวคุณเองinitStateคุณจะเห็นAssertionErrorว่าเครื่องมือของคุณไม่ทำงานตามที่ตั้งใจหรือไม่ ไม่สำคัญว่าคุณจะทำอะไรบางอย่างมาก่อนเพราะassertมีวัตถุประสงค์เพียงเพื่อรายงานว่ามีบางอย่างในรหัสของคุณผิดอยู่ดีและคุณจะเห็นว่าแม้ว่าคุณจะโทรหาsuper.initStateที่ส่วนท้ายสุดของวิธีการของคุณ

dispose

disposeวิธีการคล้ายคลึง ( แหล่งที่มา ):

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

อย่างที่คุณเห็นมันยังมีเฉพาะการยืนยันที่จัดการกับการตรวจสอบวงจรการดีบัก ข้อที่สองassertที่นี่เป็นกลอุบายที่ดีเพราะช่วยให้มั่นใจได้ว่า_debugLifecycleStateจะมีการเปลี่ยนแปลงเฉพาะในโหมดแก้ไขข้อบกพร่อง (เนื่องจากassert-statements จะดำเนินการในโหมดดีบักเท่านั้น)
ซึ่งหมายความว่าตราบใดที่คุณโทรหาที่super.dispose ใดที่หนึ่งในวิธีการของคุณเองคุณจะไม่สูญเสียคุณค่าใด ๆ หากไม่มีมิกซ์อินเพิ่มฟังก์ชันการทำงานเพิ่มเติม


1
เอกสารทางการที่กระพือปีกนั้นไม่ดีมาก :( ขอบคุณสำหรับคำตอบของคุณ :)
CopsOnRoad

ขอขอบคุณสำหรับคำอธิบายของคุณคุณจะอธิบายด้วยหรือไม่มีวิธีหนึ่งบรรทัดinitState()ซึ่งก็คือassert(...)ประโยชน์ของการโทรsuper.initState()ในแอปผลิต
CopsOnRoad

1
ขอบคุณมาก. ตอนนี้มันสมเหตุสมผลแล้ว! ดังนั้นฉันเดาว่าจะอยู่ในด้านที่ปลอดภัยกว่าและเพื่อประโยชน์ของการฝึกการเขียนโปรแกรมที่ดีก็ควรเก็บไว้ที่จุดเริ่มต้นของรหัส
K Vij

@creativecreatorormaybenot นั่นหมายความว่าทีม Flutter พ้นจากความคิดของพวกเขาโดยใช้mustCallSuperวิธีการนี้มานานกว่า 2 ปีแล้วตั้งแต่ Flutter มาถึงแล้ว ประโยชน์ของการวางไว้ที่นั่นคืออะไร?
CopsOnRoad

@creativecreatorormaybenot แม้ว่าทีมจะสร้างมันขึ้นมา แต่ก็mixinยังมีคำแถลงเดียวในเรื่องนี้initStateซึ่งก็คือassert(...)ความสำคัญของการเรียกsuper.initState()แอปที่ใช้งานจริง?
CopsOnRoad

3

super.initState()ควรเป็นบรรทัดแรกในinitStateวิธีการของคุณ

จากเอกสาร:

initState (): หากคุณแทนที่สิ่งนี้ตรวจสอบให้แน่ใจว่าวิธีการของคุณเริ่มต้นด้วยการเรียกร้องให้ super.initState ()


2

super.initState()ในขณะที่คุณจะได้เห็นในชั้นเรียนจากกรอบที่คุณควรทำทุกอย่างหลังจากเครื่องมือที่จะเริ่มต้นความหมายหลังจากที่

กรณีที่ผมทิ้งจะเป็นเหตุผลในทางอื่น ๆ super.dispose()เป็นครั้งแรกที่จะทำทุกอย่างและโทรแล้ว

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

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

ขอบคุณ. แต่ฉันสังเกตเห็นว่าในบางตัวอย่างรหัส มันถูกเรียกใช้ที่ส่วนท้ายของวิธีการเริ่มต้น ...
K Vij

นั่นคือสิ่งที่ฉันพูด
Pablo Barrera

0

initState ถูกเรียกใช้โดยค่าเริ่มต้นเมื่อใดก็ตามที่มีการเพิ่มวิดเจ็ต stateful ใหม่ลงในแผนผังวิดเจ็ต ตอนนี้ super.initState ดำเนินการเริ่มต้นการใช้งานคลาสพื้นฐานของวิดเจ็ตของคุณหากคุณเรียกอะไรก่อนหน้า super.initState ที่ขึ้นอยู่กับคลาสพื้นฐานดังนั้นนี่อาจทำให้เกิดปัญหา นี่คือเหตุผลที่แนะนำให้คุณโทรหา initState ในวิธีนี้

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

เหตุผลคือข้อบกพร่องเล็กน้อยเพราะdisposeมันเป็นสิ่งที่ตรงกันข้าม เฟรมเวิร์กคาดว่าคุณจะโทรหาsuper.dispose ตอนท้ายแต่คำแนะนำนั้นถูกต้อง
creativecreatorormaybenot

เพราะถ้าคุณเรียก super.dispose ก่อนที่จะกำจัดสิ่งอื่น ๆ ส่วนประกอบที่ขึ้นอยู่กับคลาสพื้นฐานของคุณอาจขัดแย้งกัน
Anirudh Sharma
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.