#import "../PageTemplate.typ": *
#import "@preview/treet:1.0.0": *
#import "@preview/tiaoma:0.3.0"
#set heading(numbering: "1.1", offset: 1)
#set figure(kind: image)

= Flutter <flutter>

#h(1.7em) Flutter เป็นชุดพัฒนาซอฟต์แวร์ UI แบบโอเพนซอร์สที่สร้างโดย Google
สามารถใช้พัฒนาแอปพลิเคชันข้ามแพลตฟอร์มจากฐานโคดเดียวสำหรับเว็บ Fuchsia, Android, iOS,
Linux, macOS และ#jb Windows โดย Flutter ได้รับการพูดถึงครั้งแรกในปี 2015
และเปิดตัวในเดือนพฤษภาคม 2017 และ#jb Flutter ถูกใช้งานภายในโดย Google ในแอปพลิเคชันต่างๆ
เช่น Google Pay และ Google Earth รวมถึงโดยนักพัฒนาซอฟต์แวร์รายอื่นๆ เช่น ByteDance และ
Alibaba

#h(1.7em) Flutter จะสร้างแอปพลิเคชันที่มีเอ็นจิ้นการเรนเดอร์ของตัวเอง
ซึ่งส่งข้อมูลพิกเซลไปยังหน้าจอโดยตรง ซึ่งแตกต่างจากเฟรมเวิร์ก UI อื่น ๆ
อีกมากมายที่อาศัยแพลตฟอร์มเป้าหมายเพื่อจัดหาเอ็นจิ้นการเรนเดอร์ เช่น แอป Android พื้นฐานที่ใช้
Android SDK ระดับอุปกรณ์ หรือ iOS SDK ที่ใช้ UI stack ในตัวของแพลตฟอร์มเป้าหมาย
การควบคุมขั้นตอนการแสดงผลของ Flutter ช่วยลดความยุ่งยากในการรองรับหลายแพลตฟอร์ม
เนื่องจากสามารถใช้โคด UI ที่เหมือนกันได้กับทุกแพลตฟอร์มเป้าหมาย

== Dart

#h(4.2em) Dart เป็นภาษาโปรแกรมที่ออกแบบโดย Lars Bak และ Kasper Lund และพัฒนาโดย#jb
Google สามารถใช้พัฒนาแอปพลิเคชันบนเว็บ มือถือ เซิร์ฟเวอร์ และเดสก์ท็อปได้
และยังเป็นภาษาหลักที่ใช้ในการพัฒนาแอปพลิเคชัน Flutter

#h(4.2em) Dart เป็นภาษาเชิงวัตถุ อิงคลาส และรวบรวมขยะ (garbage-collection)
ด้วยไวยากรณ์แบบ C สามารถคอมไพล์เป็นโค้ดเครื่อง JavaScript หรือ WebAssembly ได้
รองรับอินเทอร์เฟซ มิกซ์อิน คลาสนามธรรม เจเนอริกแบบรีไฟด์ และการอนุมานชนิดข้อมูล

== สถาปัตยกรรม

#h(4.2em) Flutter ถูกออกแบบมาให้เป็นระบบแบบเลเยอร์ที่ต่อขยายได้
ประกอบด้วยไลบรารีอิสระหลายชุดที่แต่ละชุดพึ่งพาเลเยอร์ที่อยู่ด้านล่าง
ไม่มีเลเยอร์ใดที่มีสิทธิ์พิเศษในการเข้าถึงเลเยอร์ด้านล่าง
และทุกส่วนของเฟรมเวิร์กถูกออกแบบมาให้เป็นตัวเลือกและสามารถทดแทนได้

#afigure(
  image("Flutter/archdiagram.png", width: 80%),
  attr: [Flutter, ภายใต้ CC BY 4.0],
  alt: "แผนผังสถาปัตยกรรม Flutter",
  caption: [สถาปัตยกรรม Flutter],
)

#v(0.5em)

#iii สำหรับระบบปฏิบัติการที่อยู่ภายใต้ แอปพลิเคชัน Flutter
จะถูกบรรจุในลักษณะเดียวกับแอปพลิเคชันเนทีฟอื่น ๆ โดยตัวฝังตัว (Embedder)
เฉพาะแพลตฟอร์มจะทำหน้าที่เป็นจุดเริ่มต้น#jb
ประสานงานกับระบบปฏิบัติการที่อยู่ภายใต้เพื่อเข้าถึงบริการต่างๆ เช่น พื้นผิวการแสดงผล การเข้าถึง
และการป้อนข้อมูล และจัดการลูปเหตุการณ์ข้อความ ตัวฝังตัวเขียนด้วยภาษาที่เหมาะสมกับแพลตฟอร์ม#jb
ปัจจุบันคือ Java และ C++ สำหรับ Android, Swift และ Objective-C/Objective-C++ สำหรับ#jb
iOS และ macOS และ C++ สำหรับ Windows และ Linux การใช้ตัวฝังตัว โค้ด Flutter
สามารถรวมเข้ากับแอปพลิเคชันที่มีอยู่แล้วในรูปแบบโมดูล หรือโค้ดอาจเป็นเนื้อหาทั้งหมดของแอปพลิเคชันก็ได้
Flutter มีตัวฝังตัวจำนวนมากสำหรับแพลตฟอร์มเป้าหมายทั่วไป แต่ก็ยังมีตัวฝังตัวอื่นๆ อีกด้วย

#iii หัวใจหลักของ Flutter คือ Flutter engine ซึ่งส่วนใหญ่เขียนด้วยภาษา C++
และรองรับฟังก์ชันพื้นฐานที่จำเป็นต่อการทำงานของแอปพลิเคชัน Flutter ทั้งหมด
เอนจินนี้มีหน้าที่ในการแปลงฉากที่ประกอบขึ้นเป็นภาพแรสเตอร์ทุกครั้งที่จำเป็นต้องวาดเฟรมใหม่
มันมีหน้าที่ให้การใช้งานระดับต่ำของ API หลักของ Flutter รวมถึงการจัดวางข้อความกราฟิก
การรับส่งข้อมูลไฟล์และเครือข่าย รันไทม์ Dart และเครื่องมือคอมไพล์

#iii เอนจินนี้ถูกเปิดเผยสู่เฟรมเวิร์ก Flutter ผ่านทาง dart:ui ซึ่งห่อหุ้มโค้ด C++
ที่อยู่เบื้องหลังด้วยคลาส Dart ไลบรารีนี้เปิดเผยส่วนประกอบพื้นฐานระดับต่ำสุด เช่น
คลาสสำหรับควบคุมระบบย่อยการรับข้อมูล กราฟิก และการแสดงผลข้อความ

#iii โดยทั่วไป นักพัฒนาจะโต้ตอบกับ Flutter ผ่านเฟรมเวิร์ก Flutter
ซึ่งเป็นเฟรมเวิร์กที่ทันสมัยและตอบสนองต่อสิ่งรอบข้าง เขียนด้วยภาษา Dart
เฟรมเวิร์กนี้ประกอบด้วยชุดไลบรารี แพลตฟอร์ม#jb เลย์เอาต์ และพื้นฐานที่ครบครัน
ซึ่งประกอบด้วยเลเยอร์หลายชั้น เริ่มจากล่างขึ้นบน ได้แก่

#[
  #set enum(indent: 4.1em)
  1. คลาสพื้นฐานและบริการส่วนประกอบต่างๆ เช่น แอนิเมชัน การวาดภาพ และท่าทางสัมผัส
    ซึ่งนำเสนอนามธรรมที่ใช้กันทั่วไปเหนือพื้นฐานที่อยู่เบื้องหลัง

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

  3. เลเยอร์วิดเจ็ตเป็นนามธรรมของการประกอบ
    วัตถุเรนเดอร์แต่ละชิ้นในเลเยอร์การเรนเดอร์จะมีคลาสที่สอดคล้องกันในเลเยอร์วิดเจ็ต นอกจากนี้
    เลเยอร์วิดเจ็ตยังช่วยให้คุณกำหนดการรวมกันของคลาสที่คุณสามารถนำกลับมาใช้ใหม่ได้
    นี่คือเลเยอร์ที่แนะนำโมเดลการเขียนโปรแกรมแบบตอบสนอง

  4. ไลบรารี Material และ Cupertino
    นำเสนอชุดควบคุมที่ครอบคลุมซึ่งใช้ส่วนประกอบพื้นฐานของเลเยอร์วิดเจ็ตเพื่อนำภาษาการออกแบบ
    Material หรือ iOS ไปใช้
]

#iii เฟรมเวิร์ก Flutter มีขนาดค่อนข้างเล็ก
ฟีเจอร์ระดับสูงหลายอย่างที่นักพัฒนาอาจใช้ถูกพัฒนาขึ้นมาในรูปแบบของแพ็กเกจ
รวมถึงปลั๊กอินของแต่ละแพลตฟอร์ม เช่น กล้องและเว็บวิว ตลอดจนฟีเจอร์ที่ไม่ขึ้นกับแพลตฟอร์ม เช่น
ตัวอักษร, HTTP และแอนิเมชัน ซึ่งสร้างขึ้นจากไลบรารีหลักของ Dart และ Flutter
แพ็กเกจบางส่วนมาจากระบบนิเวศที่กว้างกว่า ครอบคลุมบริการต่างๆ เช่น การชำระเงินภายในแอป
การตรวจสอบสิทธิ์ของ Apple และแอนิเมชัน

== โครงสร้างของแอปพลิเคชัน

#iii แผนภาพต่อไปนี้แสดงภาพรวมของส่วนประกอบต่างๆ ที่ประกอบกันเป็นแอป Flutter
ทั่วไปที่สร้างขึ้นโดยคำสั่ง `flutter create` แผนภาพนี้แสดงตำแหน่งของ Flutter Engine
ในโครงสร้างนี้ เน้นขอบเขตของ API และระบุที่เก็บโค้ด (repository) ที่ส่วนประกอบแต่ละส่วนอยู่
คำอธิบายด้านล่างจะอธิบายคำศัพท์บางคำที่ใช้กันทั่วไปในการอธิบายส่วนประกอบของแอป Flutter

#afigure(
  image("Flutter/app-anatomy.svg", width: 2.5in),
  attr: [Flutter, ภายใต้ CC BY 4.0],
  alt: "เลเยอร์ต่าง ๆ ของแอพลิเคชัน Flutter ที่ถูกสร้างโดย flutter create",
  caption: [เลเยอร์ต่าง ๆ ของแอพลิเคชัน Flutter],
)

#[
  #set enum(indent: 7.55em)
  === แอปพลิเคชัน Dart (Dart app)
  + ประกอบวิดเจ็ตเข้าด้วยกันเพื่อสร้าง UI ที่ต้องการ
  + ดำเนินการตามตรรกะทางธุรกิจ
  + นักพัฒนาแอปเป็นเจ้าของ

  === เฟรมเวิร์ก (Framework)
  1. ให้ API ระดับสูงสำหรับการสร้างแอปคุณภาพสูง (ตัวอย่างเช่น วิดเจ็ต การทดสอบการกด
    การตรวจจับท่าทาง การเข้าถึงได้ และการอินพุต ข้อความ)
  2. ประกอบต้นวิดเจ็ตของแอปพลิเคชันเป็นฉาก

  === เอนจิน (Engine)
  1. มีหน้าที่แปลงฉากเป็นรูปแบบแรสเตอร์
  2. ให้การทำงานระดับต่ำของแกนกลางของ Flutter API (เช่น กราฟิก การจัดข้อความ และรันไทม์
    Dart)
  3. เปิดเผยฟังก์ชันระดับนี้ให้แก่เฟรมเวิร์กผ่าน API `dart:ui`
  4. บูรณาการกับแพลตฟอร์มต่าง ๆ ด้วย API ตัวฝังตัว

  === ตัวฝังตัว (Embedder)
  1. ประสานงานกับระบบปฏิบัติการภายใต้สำหรับการเข้าถึงบริการต่าง ๆ เช่น พื้นผิวการเรนเดอร์
    การเข้าถึง และการป้อนข้อมูล
  2. จัดการลูปอิเวนต์
  3. เปิดเผย API เฉพาะแพลตฟอร์มเพื่อบูรณาการตัวฝังตัวเข้าไปยังแอป

  === ตัวรัน (Runner)
  1. ประกอบชิ้นส่วนที่ถูกเปิดเผยโดยตัวฝังตัวเข้าเป็นแพคเกจแอปพลิเคชันที่สามารถใช้งานได้บนแพลตฟอร์มเป้าหมาย
  2. บางส่วนถูกสร้างขึ้นโดย `flutter create` และมีเจ้าของเป็นผู้พัฒนาแอป
]

== ระบบการดีไซน์

#iii โดยใน Flutter แล้วนั้น ไม่รวมแพคเกจบุคคลที่สาม จะมีระบบการดีไซน์อยู่สองแบบคือ:

#[
  #set enum(indent: 4.10em)
  + Material Design คือการดีไซน์ของ Google สำหรับ Android
  + Cupertino Design คือการดีไซน์ของ Apple สำหรับ iOS
]

#iii อย่างไรก็ตาม Cupertino Design ถูกแทนที่โดย Liquid Glass แล้ว โดยในปัจจุบันทีม Flutter
กำลังทำการตรวจสอบและแก้ไขโครงสร้างระบบดีไซน์ ดังนั้น หากมีผู้พัฒนาต้องการใช้เอฟเฟกต์#jb Liquid
Glass ในแอปพลิเคชัน Flutter จึงจำเป็นต้องพึงพาแพคเกจบุคคลที่สามก่อนในขณะนี้ (Flutter เวอร์ชัน
3.38.5 ณ เวลาที่พิมพ์)

#iii Material Design คือภาษาการดีไซน์ที่ถูกพัฒนาโดย Google และถูกเปิดตัวครั้งแรก 25 มิถุนายน
2014 และมีเวอร์ชันหลัก 3 เวอร์ชันด้วยกัน โดยที่เวอร์ชันที่ 3 ถูกเปิดตัวในงาน Google I/O 2021
และมีชื่อว่า "Material You" (แต่ชื่อธรรมดา "Material Design 3" ก็ยังถูกใช้งานกันอย่างปกติ)#jb
และในงาน Google I/O 2025 มีการเปิดตัว "Material 3 Expressive"
ซึ่งเป็นการปรับปรุงต่อจาก#jb Material You เดิมสำหรับ Android 16 และ Wear OS 6
และสามารถดูรายละเอียดเพิ่มเติมเกี่ยวกับ Material 3 ได้ที่ https://m3.material.io/

== ส่วนติดต่อผู้ใช้ที่มีปฏิกิริยา

#iii บนพื้นผิว Flutter เป็นเฟรมเวิร์ก UI แบบ reactive และ declarative
ซึ่งนักพัฒนาเป็นผู้จัดเตรียมการแมปจากสถานะแอปพลิเคชันไปยังสถานะอินเทอร์เฟซ
และเฟรมเวิร์กจะทำหน้าที่อัปเดตอินเทอร์เฟซขณะรันไทม์เมื่อสถานะของแอปพลิเคชันเปลี่ยนแปลง
โมเดลนี้ได้รับแรงบันดาลใจจากงานที่มาจาก Facebook สำหรับเฟรมเวิร์ก React ของพวกเขา
ซึ่งรวมถึงการทบทวนหลักการออกแบบแบบดั้งเดิมหลายประการ

#iii ในเฟรมเวิร์ก UI แบบดั้งเดิมส่วนใหญ่ สถานะเริ่มต้นของอินเทอร์เฟซผู้ใช้จะถูกอธิบายเพียงครั้งเดียว
จากนั้นจึงอัปเดตแยกกันด้วยโคดผู้ใช้ ณ รันไทม์ เพื่อตอบสนองต่อเหตุการณ์
ความท้าทายประการหนึ่งของแนวทางนี้คือ เมื่อแอปพลิเคชันมีความซับซ้อนมากขึ้น
นักพัฒนาจำเป็นต้องทราบว่าสถานะเปลี่ยนแปลงไปอย่างไรตลอดทั้ง UI ตัวอย่างเช่น พิจารณา UI ต่อไปนี้:

#afigure(
  image("Flutter/color-picker.png", width: 70%),
  alt: "หน้าต่างเลือกสี",
  caption: [หน้าต่างเลือกสี],
)

#v(0.5em)

#iii มีหลายที่ที่สามารถเปลี่ยนสถานะได้ กล่องสี, แถบเลื่อนเฉดสี, ​​ปุ่มตัวเลือก เมื่อผู้ใช้โต้ตอบกับ UI
การเปลี่ยนแปลงจะต้องสะท้อนให้เห็นในทุกที่ ที่เลวร้ายยิ่งกว่านั้น เว้นแต่จะได้รับการดูแล
การเปลี่ยนแปลงเล็กน้อยในส่วนใดส่วนหนึ่งของอินเทอร์เฟซผู้ใช้อาจทำให้เกิดเอฟเฟกต์คลื่นส่งผลกระทบกับโค้ดที่ดูเหมือนจะไม่เกี่ยวข้องกัน

#iii วิธีแก้ปัญหาอย่างหนึ่งคือแนวทางเช่น MVC
โดยที่คุณส่งข้อมูลการเปลี่ยนแปลงไปยังโมเดลผ่านคอนโทรลเลอร์
จากนั้นโมเดลจะพุชสถานะใหม่ไปยังมุมมองผ่านคอนโทรลเลอร์ อย่างไรก็ตาม#jb สิ่งนี้ก็เป็นปัญหาเช่นกัน
เนื่องจากการสร้างและการอัปเดตองค์ประกอบ UI
เป็นขั้นตอนสองขั้นตอนที่แยกจากกันซึ่งอาจไม่ซิงค์กันได้อย่างง่ายดาย

#iii Flutter พร้อมด้วยเฟรมเวิร์กเชิงโต้ตอบอื่น ๆ ใช้แนวทางอื่นในการแก้ไขปัญหานี้
โดยแยกอินเทอร์เฟซผู้ใช้ออกจากสถานะพื้นฐานอย่างชัดเจน ด้วย API สไตล์ React
คุณจะสร้างเฉพาะคำอธิบาย UI เท่านั้น
และเฟรมเวิร์กจะดูแลการใช้การกำหนดค่านั้นเพื่อสร้างหรืออัปเดตอินเทอร์เฟซผู้ใช้ตามความเหมาะสม

#iii ใน Flutter วิดเจ็ต (คล้ายกับส่วนประกอบใน React)
จะแสดงด้วยคลาสที่ไม่เปลี่ยนรูปซึ่งใช้ในการกำหนดค่าแผนผังของวัตถุ
วิดเจ็ตเหล่านี้ถูกใช้เพื่อจัดการแผนผังวัตถุที่แยกจากกันสำหรับโครงร่าง
ซึ่งจากนั้นจะใช้ในการจัดการแผนผังวัตถุที่แยกจากกันสำหรับการประกอบ หัวใจหลักของ Flutter
คือชุดของกลไกในการอัพเดทส่วนที่ดัดแปลงของแผนผังวิดเจ็ตอย่างมีประสิทธิภาพ
การแปลงแผนผังหลายแผนผังของวัตถุให้เป็นแผนผังระดับล่างของวัตถุ
และการแพร่กระจายการเปลี่ยนแปลงไปยังแผนผังวิดเจ็ตเหล่านี้

#iii วิดเจ็ตประกาศส่วนติดต่อผู้ใช้โดยการเขียนทับเมธอด `build()` ซึ่งเป็นฟังก์ชันที่แปลงสถานะเป็น UI

#afigure(
  ```
  UI = f(state)
  ```,
  kind: image,
  caption: [สูตรแสดงการทำงานอย่างคร่าว],
)

#iii เมธอด `build()` นั้นตามการออกแบบแล้วเป็นเมธอดที่เร็วและควรที่จะไม่มีผลข้างเคียง
ทำให้เมธอดนั้นสามารถถูกเรียกใช้โดยเฟรมเวิร์กเมื่อไหร่ก็ได้ที่จำเป็น
(เป็นไปได้ที่จะบ่อยมากและมีการเรียกใช้หนึ่งครั้งต่อหนึ่งเฟรม)

#iii วิธีนี้พึ่งพาลักษณะเฉพาะรันไทม์ภาษา (หากเจาะจงคือการสร้างและทำลายวัตถุอย่างรวดเร็ว)#jb ซึ่ง
Dart นั้นเหมาะสำหรับงานนี้เป็นพิเศษ

== ประวัติ

#iii Flutter เวอร์ชันแรกรู้จักกันในชื่อ "Sky" และทำงานบนระบบปฏิบัติการ Android
มีการเปิดเผยในการประชุมสุดยอดนักพัฒนา Dart ประจำปี 2015
โดยมีจุดประสงค์ที่ระบุไว้คือสามารถแสดงผลได้อย่างสม่ำเสมอที่ 120 เฟรมต่อวินาที เมื่อวันที่ 4 ธันวาคม
2018 Flutter 1.0 เปิดตัวในการประชุม Flutter ที่ลอนดอน

#iii ในวันที่ 6 พฤษภาคม 2020 ชุดพัฒนาซอฟต์แวร์ (SDK) Dart เวอร์ชัน 2.8 และ Flutter 1.17.0
ได้รับการเผยแพร่ โดยเพิ่มการรองรับ Metal API

#iii เมื่อวันที่ 3 มีนาคม 2021 Google ได้เปิดตัว Flutter 2 ระหว่างกิจกรรม Flutter Engage
ออนไลน์ ได้เพิ่มตัวเรนเดอร์ที่ใช้ Canvas สำหรับเว็บ นอกเหนือจากตัวเรนเดอร์ที่ใช้ HTML
และการสนับสนุนแอปพลิเคชันเดสก์ท็อปแบบทดลองสำหรับ Windows, macOS, และ Linux
นอกจากนี้ยังมาพร้อมกับ Dart 2.0 ซึ่งรวมถึงการสนับสนุนด้านความปลอดภัยแบบ null (null-safety)
ความปลอดภัยแบบ null เป็นทางเลือกในตอนแรกเนื่องจากเป็นการเปลี่ยนแปลงครั้งใหญ่และบังคับใช้ใน
Dart 3 ที่เปิดตัวในปี 2023

#iii ในวันที่ 12 พฤษภาคม 2022 Flutter 3 และ Dart 2.17
ได้รับการเผยแพร่โดยมีการรองรับแพลตฟอร์มเดสก์ท็อปทั้งหมดอย่างเสถียร

#iii เมื่อวันที่ 27 ตุลาคม 2024 นักพัฒนาชุมชน Flutter จำนวนหนึ่งได้ประกาศเปิดตัว Flock
ซึ่งเป็นเวอร์ชันแยกของ Flutter ที่มีจุดประสงค์เพื่อให้ง่ายต่อการร่วมพัฒนา
ในขณะเดียวกันก็ยังคงรักษาความสอดคล้องกับทุกการเปลี่ยนแปลงที่เกิดขึ้นในโค้ดต้นทาง

#iii ในปี 2025 Google ยังคงพัฒนา Flutter ต่อไปด้วยสถาปัตยกรรมแบบโมดูลาร์ที่ได้รับการปรับปรุง
การรองรับอุปกรณ์พับได้ และการเพิ่มประสิทธิภาพ ARM IoT ตามที่ระบุไว้ในแผนงานฉบับปรับปรุง
