ข้ามไปยังเนื้อหา

Navigator & Routes

Navigator คือ widget ที่จัดการ stack ของ route โดย route หนึ่งคือหน้าจอหนึ่ง route ที่อยู่ top สุดของ stack คือสิ่งที่ user เห็น navigation ก็แค่ operation บน stack สองอย่าง: push route ใหม่ขึ้น top หรือ pop route บนสุดออกเพื่อเผยตัวที่อยู่ข้างใต้

flowchart TB
  subgraph stack["route stack"]
    top["DetailScreen  (visible, top)"]
    mid["ListScreen"]
    bottom["HomeScreen  (bottom)"]
  end
  top -->|pop| mid
  mid -->|push DetailScreen| top
Navigator คือ stack ของ route

ปุ่ม back ของเครื่อง, ลูกศร back บน app bar และ swipe-back gesture ทั้งหมดทำสิ่งเดียวกัน: pop route ที่อยู่ top

คุณเอา Navigator มาจาก BuildContext ปัจจุบันด้วย Navigator.of(context) แล้ว push route ตัว MaterialPageRoute ให้ transition animation ที่ถูกต้องตาม platform มาฟรี

// Push a new screen onto the stack.
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => const DetailScreen()),
);
// Pop back to the previous screen.
Navigator.of(context).pop();

builder คือ function ที่ return widget ของหน้าจอ — รันตอน route ถูกสร้าง ไม่ใช่ตอนคุณเรียก push

วิธีที่สะอาดที่สุดในการส่งข้อมูลไปหน้าจอถัดไปคือ constructor argument ธรรมดา ไม่มีเวทมนตร์ ไม่มี global state — แค่ส่งเข้าไป

Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => DetailScreen(userId: 42),
),
);
// DetailScreen receives it like any widget:
class DetailScreen extends StatelessWidget {
const DetailScreen({super.key, required this.userId});
final int userId;
// ...
}

Navigator.push return Future ที่ complete เมื่อ route ที่ push ถูก pop — คุณจึง await ผลลัพธ์ที่ user เลือกบนหน้าจอถัดไปได้ (การเลือก, การยืนยัน)

// Caller awaits the result of the pushed screen.
final picked = await Navigator.of(context).push<Color>(
MaterialPageRoute(builder: (context) => const ColorPicker()),
);
if (picked != null) {
// use the returned Color
}
// Inside ColorPicker, return a value by passing it to pop:
Navigator.of(context).pop(Colors.blue);

สำหรับแอปเล็ก ๆ คุณลงทะเบียน named route ใน MaterialApp แล้ว navigate ด้วยชื่อที่เป็น string ได้ วิธีนี้รวม route table ไว้ที่เดียว แต่ระวัง: named route จะยุ่งยากเมื่อต้องส่ง argument ที่มี type และเมื่อทำ deep link นั่นคือเหตุผลที่ ecosystem ย้ายไป declarative routing (บทถัดไป)

MaterialApp(
routes: {
'/': (context) => const HomeScreen(),
'/settings': (context) => const SettingsScreen(),
},
);
Navigator.of(context).pushNamed('/settings');
Navigator จัดการ data structure แบบไหน?
วิธีที่แนะนำในการส่งข้อมูลไปหน้าจอถัดไปคืออะไร?
จะรับค่ากลับจากหน้าจอที่ user โต้ตอบด้วยอย่างไร?
ทำไม ecosystem ถึงย้ายออกจาก named route สำหรับแอปใหญ่?