Life cycle ของ Flutter
มาต่อกับชาเลนจ์ จากเด็กจบใหม่ที่ต้องติดบ้านเพราะโควิดสู่นักพัฒนา Flutter #5
วงจรชีวิตของ Flutter จากที่ผมศึกษามาจะมี StatelessWidget กับ StatefulWidget
StatefulWidget
จากที่เคยบอกไปตอนบทแรกๆว่า StatefulWidget นั้นเหมาะกับหน้าที่มีการเปลี่ยนแปลงอยู่ตลอดเพราะมี State ที่สามารถจัดการข้อมูลที่มีการเปลี่ยนแปลงได้และจะสั่ง build ใหม่ด้วยตัวมันเอง
จากรูปด้านบนเรามาดูไปทีละตัวเริ่มจาก
1. Constructor
ไว้รับค่าจาก Page อื่นๆ ที่เรียก Page นี้ (ถ้ามี) และยังไม่สามารถใช้ State ได้เพราะยังไม่เกิดขึ้นมา
2. createState
เมื่อสร้าง StatefulWidget ใหม่จะเรียกcreateState()
ทันทีหลังนั้นก่อนที่จะเรียก initState จะมีค่านึงที่เชื่อมความสัมพันธ์ระหว่าง State และ BuildContext เรียกว่า mounted และจะอยู่จนกว่า framework จะเรียก dispose
3. initState
function นี้จะถูกเรียกครั้งเดียวใน life cycle และห้ามลืม super.initState()
ใน method นี้จะมี context มาแล้ว แต่ยังไม่ควรใช้เพราะว่าตัว Framework ยังจัดการ state ไม่เรียบร้อยครับและ function นี้เหมาะกับการ Initialize data
addPostFrameCallback เป็น callback จบการวาด frame ทำให้มั่นใจได้ว่า Widget build เสร็จเรียบร้อย
import 'package:flutter/scheduler.dart';@override
void initState() {
super.initState();
SchedulerBinding.instance.addPostFrameCallback((_) => {});
}
4. didChangeDependencies
function จะถูกเรียกครั้งแรกหลัง initState ทำงานเสร็จทันทีและจะถูกเรียกอีกครั้งก็ต่อเมื่อ data ที่มีผลต่อ widget ถูกอัปเดต
ขณะนี้ context พร้อมให้นักพัฒนาใช้แล้วควร super.didChangeDependencies() เป็นอันดับแรกซึ่ง function นี้เหมาะกับการ Initialize listeners
5. didUpdateWidget
function จะถูกเรียกเมื่อ parent Widget ถูกเปลียนและต้องการที่จะวาด UI ใหม่และส่วนใหญ่ที่ใช้ ก็ต่อเมื่อต้องการจะเทียบ oldWidget parameter กับ widget ปัจุจบันว่ามีอะไรต่างไหมหรืออยากจะเพิ่ม logic ก็สามารถทำได้
6. build()
คิดว่าทุกคนน่าจะรู้จักกันดีเพราะใช้ในการสร้าง widget ของเราและถ้าต้องการจะให้มัน re-build ก็สามารถทำได้ด้วยการเรียก method setState()
7. deactivate
จะถูกเรียกก็ต่อเมื่อมี object ถูก removed from the tree ก่อน dispose จะถูกเรียก
8. dispose
ถูกเรียกเมื่อ widget กำลังจะหายไปจากหน้าจอ
ควร Override ก็ต่อเมื่อผู้อ่านต้องการ cleanup (e.g. listeners, controllers…) หลังจากนั้นอย่าลืมเรียก super.dispose() ด้วยนะครับ
จะถูกเรียกใช้ก็ต่อเมื่อ App เข้าสู่ background และกลับเข้ามาใช้ foreground
- inactive : App is in an inactive state and is not receiving user input.
- paused : App running in the background.
- resumed : App back to foreground.
- detached : เมื่อ Page หรือ App นั้นถูกทำลาย
Test lifecycle Android
Foreground
I/flutter (32627): initState
I/flutter (32627): didChangeDependencies
I/flutter (32627): addPostFrameCallback
Background
I/flutter (355): state = AppLifecycleState.inactive
I/flutter (355): state = AppLifecycleState.paused
กลับเข้า App มาใหม่
I/flutter (355): state = AppLifecycleState.resumed
เมื่อ Kill App
I/flutter (355): state = AppLifecycleState.inactive
I/flutter (355): state = AppLifecycleState.paused
I/flutter (355): state = AppLifecycleState.detached
Test lifecycle IOS
Foreground
flutter: initState
flutter: didChangeDependencies
flutter: addPostFrameCallback
flutter: state = AppLifecycleState.resumed
flutter: state = AppLifecycleState.resumed
Background
flutter: state = AppLifecycleState.inactive
flutter: state = AppLifecycleState.paused
กลับเข้า App มาใหม่
flutter: state = AppLifecycleState.inactive
flutter: state = AppLifecycleState.resumed
เมื่อ Kill App
flutter: state = AppLifecycleState.inactive
flutter: state = AppLifecycleState.paused
โค้ดที่ทดสอบ lifecycle
StatelessWidget
class Lifecycle extends StatelessWidget {
final parameter; Lifecycle({Key key, this.parameter}) : super(key: key); @override
Widget build(BuildContext context) {
return Container();
}
}
จากที่เคยบอกไปตอนบทแรกๆว่า StatelessWidget นั้นเหมาะกับการแสดงค่าที่ไม่เปลี่ยนแปลงหรือค่าคงทีเพราะ life cycle ของ StatelessWidget นั้นมีแค่
- ไว้รับค่าจาก Page อื่นๆที่เรียก Page นี้ (ถ้ามี)
- สร้าง
- แสดงผลผ่าน method build
วันนี้ขอจบบทความเท่านี้นะครับ ถ้ามีอะไรติชมเขียนมาได้เลยนะครับ ผมจะได้เอาไปปรับปรุงในบทความต่อไป ขอบคุณที่อ่านจนจบครับ