การใช้งาน FutureBuilder ที่เป็น Async widgets ใน Flutter
เขียนเมื่อ 2 ปีก่อน โดย Ninenik Narkdeefuturebuilder flutter async widgets future
คำสั่ง การ กำหนด รูปแบบ ตัวอย่าง เทคนิค ลูกเล่น การประยุกต์ การใช้งาน เกี่ยวกับ futurebuilder flutter async widgets future
ไปที่
Copy

เนื้อหาตอนต่อไปนี้ จะมาดูเกี่ยวกับการใช้งาน async widgets
ที่ชื่อว่า FutureBuilder เป็น widget ที่จะจัดการกับข้อมูลสุดท้าย
ที่จะได้รับในอนาคต เกี่ยวกับเรื่องนี้ เราต้องเข้าใจเกี่ยวกับรูปแบบ
การใช้งาน Asynchronous Programming ในภาษา Dart ทบทวน
ได้ที่บทความ
การใช้งาน Asynchronous Programming ในภาษา Dart เบื้องต้น http://niik.in/949
https://www.ninenik.com/content.php?arti_id=949 via @ninenik
*เนื้อหานี้ใช้เนื้อหาต่อเนื่องจากบทความ http://niik.in/961
จำลองข้อมูลในอนาคตด้วย Future
เราจะจำลองข้อมูลที่จะได้มาในอนาคต ความหมายที่จะสื่อก็คือ เช่น เราดึงข้อมูล
ผ่านเครือข่าย ก็จำเป็นจะต้องรอสักพักกว่าข้อมูลจะมา ก็เกิดเวลาที่ต้องรอขึ้น
ตัวอย่าง
// จำลองข้อมูลที่จะได้ หรือจะเกิดในอนาคต final Future<String> _calculation = Future<String>.delayed( const Duration(seconds: 2), () => 'Data Loaded', );
เรากำหนดตัวแปรชื่อ _calculation เป็นข้อมูล Future ที่มีชนิดข้อมูลเป็นข้อความ String โดยสร้าง
จากการกำหนดเวลาหน่วงการคืนค่าจากคำสั่ง Future<String>.delayed() พอครบ 2 วินาทีก็ให้คืนคำว่า
'Data Loaded' กลับมา เหตุผลที่เราต้องรู้จักกับข้อมูล Future ก็เพราะว่า ตัว FutureBuilder widget
ที่เราจะใช้งานในบทความนี้จำเป็นต้องใช้ข้อมูล Future นั่นเอง
ส่วนของไฟล์ home.dart ก่อนกำหนดใช้งาน FutureBuilder
class _HomeState extends State<Home> { @override Widget build(BuildContext context) { print("build");// สำหรับทดสอบ return Scaffold( appBar: AppBar( title: Text('Home'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text('Home Screen'), ], ) ), ); } }
รูปแบบการใช้งาน FutureBuilder
FutureBuilder<String>( // กำหนดชนิดข้อมูล future: _calculation, // ข้อมูล Future //builder: (BuildContext context, AsyncSnapshot snapshot) { builder: (context, snapshot) { // สร้าง widget เมื่อได้ค่า snapshot ข้อมูลสุดท้าย if (snapshot.hasData) { // ถ้าได้ค่าข้อมูลสุดท้าย return Text('Completed'); } else if (snapshot.hasError) { // ถ้ามี error return Text('${snapshot.error}'); } // ค่าเริ่มต้น, แสดงตัว Loading. return const CircularProgressIndicator(); }, ),
ส่วนแรกเป็นส่วนของการกำหนดชนิดของข้อมูล Future เราต้องกำหนดให้ถูกต้อง อย่างข้างตันเรา
กำหนดเป็น <String> มาจากข้อมูล Future<String> ถ้าเป็นข้อมูลอื่นเช่น List<String> เราก็จะ
กำหนดเป็น <List<String>> แบบนี้เป็นต้น
ส่วนที่สองเป็นข้อมูล future ก็ตัวแปรข้อมูล Future หรือจะเรียกฟังก์ชั่นมาใช้เลยก็ได้ ในตัวอย่างเรากำหนด
ค่าเป็น _calculation เป็นค่าที่เราจะใช้งาน
คำสั่ง builder จะรอทำคำสั่งสร้าง widget โดยอาศัยข้อมูลสุดท้ายที่เรียกว่า snapshot ที่ได้จากข้อมูล
Future เป็นข้อมูล AsyncSnapshot ซึ่งต้องรอข้อมูลหรือมีเวลาที่ต้องรอ จะได้ผลลัพธ์สุดท้าย
ในคำสั่ง builder เราก็จะ return Widget ที่ต้องการออกไปแสดง โดยมีเงื่อนไข ทำการตรวจสอบข้อมูล
snapshot ใน 3 รูปแบบ หรือจะเขียน 2 รูปแบบตามตัวอย่างด้านบนก็ได้ โดยไม่ต้องมี else ในเงื่อนไขสุดท้าย
คือถ้ามีข้อมูล ก็แสดงด้วย Text ข้อความคำว่า Completed ถ้ามี error ก็แสดงข้อความ error และถ้าไม่เข้า
เงื่อนไขทั้งสอง ก็แสดงตัว loading ด้วย CircularProgressIndicator widget
ตัวอย่างกรณี error ก็เช่น ในคำสั่งดึงข้อมูล Future เกิด Exception ขึ้น
// จำลองข้อมูลที่จะได้ หรือจะเกิดในอนาคต final Future<String> _calculation = Future<String>.delayed( const Duration(seconds: 5), () => throw Exception("ข้อมูลไม่พร้อมใช้งาน"), // 'Data Loaded', );
แทนที่จะส่งข้อความคำว่า 'Data Loaded' ก็เกิด error ขึ้นและส่งค่า Exception กลับมา ก็จะเข้าเงื่อนไขที่สอง
นอกจากเราจะใช้การตรวจสอบการมีข้อมูลของ snapshot ด้วยคำสั่ง snapshot.hasData ที่จะคืนค่าเป็น true / false
แล้ว เรายังสามารถใช้การตรวจสอบ สถานะการเชื่อมต่อจากค่าของ snapshot.connectionState ได้ โดยจะมีด้วยกัน
สองค่า คือ ConnectionState.waiting และ ConnectionState.done โดยเมื่อเริ่มต้นดึงข้อมูล Future ก็จะขึ้น waiting
ในครั้งแรก และเมื่อได้ข้อมูลกลับมา หรือเกิด error ก็จะขึ้น done
เราสามารถเขียนตรวจสอบแบบง่ายอย่างนี้ก็ได้
if (snapshot.connectionState == ConnectionState.done) { return Text('Completed'); } // ค่าเริ่มต้น, แสดงตัว Loading.สถานะ ConnectionState.waiting return const CircularProgressIndicator();
อย่างไรก็ตาม ควรใช้แบบวิธีแรกจะครอบคลุมการทำงานมากกว่า เพราะกรณีที่สอง หากมี error ก็ยังมีค่า
connectionState เป็น done เหมือนกัน หากไม่เขียนคำสั่งเพิ่มเพื่อตรวจสอบอีก ก็จะกลายเป็น ส่ง Text
ข้อความ 'Completed' ออกไป วิธีนี้จึงจะไม่ค่อยครอบคลุมเท่าไหร่
มาดูตัวอย่างโค้ด และผลลัพธ์การทำงาน ไฟล์ home.dart
import 'package:flutter/material.dart'; class Home extends StatefulWidget { static const routeName = '/'; const Home({Key? key}) : super(key: key); @override State<StatefulWidget> createState() { return _HomeState(); } } class _HomeState extends State<Home> { // จำลองข้อมูลที่จะได้ หรือจะเกิดในอนาคต final Future<String> _calculation = Future<String>.delayed( const Duration(seconds: 5), () => 'Data Loaded', // throw Exception("ข้อมูลไม่พร้อมใช้งาน") ); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Home'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ FutureBuilder<String>( // กำหนดชนิดข้อมูล future: _calculation, // ข้อมูล Future //builder: (BuildContext context, AsyncSnapshot snapshot) { builder: (context, snapshot) { // สร้าง widget เมื่อได้ค่า snapshot ข้อมูลสุดท้าย if (snapshot.hasData) { // ถ้าได้ค่าข้อมูลสุดท้าย return Text('Completed'); } else if (snapshot.hasError) { // ถ้ามี error return Text('${snapshot.error}'); } // ค่าเริ่มต้น, แสดงตัว Loading.สถานะ ConnectionState.waiting return const CircularProgressIndicator(); }, ), ], ) ), ); } }
ผลลัพธ์

เริ่มต้นเราไปอยู่ที่หน้า Settings จากนั้นคลิกมาหน้า Home ที่เราใช้งาน FutureBuilder ตัว Loading
จะแสดงประมาณ 5 วินาทีตามค่าที่กำหนด แล้วขึ้นข้อความว่า Completed
เรามาจำลองการสร้างข้อมูล Future โดยใช้งานเป็นแบบฟังก์ชั่น ให้เสมือนกับเราจะดึงข้อมูลใน
ฝั่งของ server มาใช้งาน จะได้เป็นดังนี้
class _HomeState extends State<Home> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Home'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ FutureBuilder<String>( // กำหนดชนิดข้อมูล future: fetchData(), // ข้อมูล Future //builder: (BuildContext context, AsyncSnapshot snapshot) { builder: (context, snapshot) { // สร้าง widget เมื่อได้ค่า snapshot ข้อมูลสุดท้าย if (snapshot.hasData) { // ถ้าได้ค่าข้อมูลสุดท้าย return Text('Completed'); } else if (snapshot.hasError) { // ถ้ามี error return Text('${snapshot.error}'); } // ค่าเริ่มต้น, แสดงตัว Loading.สถานะ ConnectionState.waiting return const CircularProgressIndicator(); }, ), ], ) ), ); } } // จำลองใช้เป็นแบบฟังก์ชั่น ให้เสมือนดึงข้อมูลจาก server Future<String> fetchData() async { final response = await Future<String>.delayed( const Duration(seconds: 5), () => 'Data Loaded', ); return response; }
เราสร้างฟังก์ชั่นชื่อว่า fetchData() แยกออกมา แล้วเรียกใช้ในส่วนของการกำหนดค่า future property
ของ FutureBuilder widget ผลลัพธ์ที่ได้ก็จะเหมือนกับวิธีแรก แต่ที่เราทำเพิ่มในรูปแบบนี้ก็พี่จำลองการทำงาน
ให้เสมือนการไปดึงข้อมูลในฝั่ง server
เนื้อหาตอนนี้ ถือได้ว่าเราได้ทำความเข้าใจเบื้องต้นกับการใช้งาน FutureBuilder widget เป็นการปูพื้นฐาน
สำหรับเนื้อหาในลำดับต่อๆ ไป รอติดตาม
กด Like หรือ Share เป็นกำลังใจ ให้มีบทความใหม่ๆ เรื่อยๆ น่ะครับ

อ่านต่อที่บทความ
-
25 Oct2021การใช้งาน StreamBuilder จัดการข้อมูล Stream ใน Flutter อ่าน 5,022
ในตอนที่แล้วเรารู้จักกับ FutureBuilder ซึ่งเป็น async widgets หนึ่งใน Flu
เนื้อหาที่เกี่ยวข้อง
-
04 Dec2019การใช้งาน Stateless และ Stateful Widget ใน Flutter เบื้องต้น อ่าน 27,721
เนื้อหาตอนที่แล้ว เราได้ทำการสร้าง App เริ่มต้น โดยใช้งาน widget มาประกอบ
-
06 Dec2019แนะนำ Basic Widget ที่ควรรู้สำหรับใช้งาน Flutter เบื้องต้น อ่าน 21,919
เนื้อหาตอนที่แล้ว เราได้ทำความเข้าใจเบื้องต้นเกี่ยวกับ การใช้งาน Stateles
-
07 Dec2019การติดตั้งและใช้งาน Package ภายนอก ใน Flutter เบื้องต้น อ่าน 10,472
เนื้อหาตอนต่อไปนี้ เราจะมาดูเกี่ยวกับการติดตั้ง Package จาก ภายนอก เพื่อม
-
09 Dec2019การกำหนด และใช้งาน ListView Widget ใน Flutter เบื้องต้น อ่าน 16,249
ต่อจากตอนที่แล้ว ที่เราได้ใช้งาน Package จากภายนอก สำหรับสร้าง random wor
-
12 Dec2019การใช้งาน Navigator และ Routing ใน Flutter เบื้องต้น อ่าน 18,521
ก่อนที่เราจะเข้าสู่เนื้อหาการประยุกต์ต่อจากตอนที่แล้ว เนื่้องจาก สิ่งที่เ
-
15 Dec2019การใช้งาน Theme และรู้จักกับ InheritedWidget ใน Flutter อ่าน 9,181
ก่อนที่เราจะไปประยุกต์การใช้งาน Theme กับโปรเจ็คจาก เนื้อหาบทความของตอนที
-
17 Dec2019การใช้งาน Drawer กำหนด SideMenu ใน Flutter เบื้องต้น อ่าน 13,393
เนื้อหาตอนต่อไปนี้ เราจะมาประยุกต์ใช้งาน Drawer ในโปรเจ็ค App ของเราต่อ จ
-
18 Dec2019การใช้งาน BottomNavigationBar ใน Flutter เบื้องต้น อ่าน 18,274
ในตอนที่แล้ว เราได้รู้จัก การใช้งาน Drawer หรือที่เรียกว่า SideMenu เบื้อ
-
21 Oct2021แสดงข้อความด้านล่างหน้าจอด้วย SnackBar ใน flutter อ่าน 2,768
SnackBar เป็น widget ที่เราสามารถใช้สำหรับแสดง popup ข้อความ แ
-
22 Oct2021การกำหนดเพิ่ม Fonts เพื่อใช้งานใน App ของ Flutter อ่าน 3,998
เนื้อหานี้จะมาแนะนำแนวทางการเพิ่มฟอนท์สำหรับ ใช้งานใน app กรณีเราอยากได้ร
-
23 Oct2021จัดการ Tab ด้วย TabController ใน Flutter อ่าน 7,688
เนื้อหานี้มาดูเกี่ยวกับการใช้งาน tab ใน flutter ซึ่งเป็นรูปแบบ การใช้งานท
-
กำลังอ่านเนื้อหานี้อยู่24 Oct2021การใช้งาน FutureBuilder ที่เป็น Async widgets ใน Flutter อ่าน 5,512
เนื้อหาตอนต่อไปนี้ จะมาดูเกี่ยวกับการใช้งาน async widgets ที่ชื่อว่า Futu
-
25 Oct2021การใช้งาน StreamBuilder จัดการข้อมูล Stream ใน Flutter อ่าน 5,022
ในตอนที่แล้วเรารู้จักกับ FutureBuilder ซึ่งเป็น async widgets หนึ่งใน Flu
URL สำหรับอ้างอิง
Top
Copy
ขอบคุณทุกการสนับสนุน
![]()