การใช้งาน Http ดึงข้อมูลจาก Server มาแสดงใน Flutter
เขียนเมื่อ 1 ปีก่อน โดย Ninenik Narkdeefuturebuilder http package listview flutter
คำสั่ง การ กำหนด รูปแบบ ตัวอย่าง เทคนิค ลูกเล่น การประยุกต์ การใช้งาน เกี่ยวกับ futurebuilder http package listview flutter
ไปที่
Copy
ตัวอย่างการเพิ่ม รูปเพิ่มผิดที่ ให้เพิ่มใน dependencies




เนื้อหาตอนต่อไปนี้ เราจะมาดูเกี่ยวกับวิธีการดึงข้อมูลจาก Server
ที่เป็นข้อมูล API มาแสดงใน app ของ flutter ซึ่งจากที่ได้เกริ่นมาแล้ว
ในหลายตอน และได้แนะนำการใช้งาน FutureBuilder สำหรับใช้งาน
ร่วมกับข้อมูล Future ซึ่งเป็นข้อมูลลักษณะเดียวกันที่เราจะได้จากการ
ไปดึงข้อมูลบน server ทบทวนเนื้อหาเกี่ยวกับ FutureBuilder
การใช้งาน FutureBuilder ที่เป็น Async widgets ใน Flutter http://niik.in/1036
https://www.ninenik.com/content.php?arti_id=1036 via @ninenik
*เนื้อหานี้ใช้เนื้อหาต่อเนื่องจากบทความ http://niik.in/961
ตัวอย่างการแสดงลิสรายการใน ListView
ก่อนเข้าไปในรายละเอียดของเนื้อหา มาดูรูปแบบการจัดการ ListView ที่เราจะใช้งาน โดย
จะจำลองข้อมูล วิธีการแสดงข้อมูล ดังนี้
ไฟล์ home.dart
import 'dart:math'; 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> { // จำลองข้อมูล สร้างลิสรายการ 100 รายการ List<String> items = List<String>.generate(100, (i) => 'Item ${i+1}'); @override void initState() { print("initState"); // สำหรับทดสอบ super.initState(); } void _refreshData(){ setState(() { print("setState"); // สำหรับทดสอบ Random rng = Random(); // ข้อมูล Random int rd_number = rng.nextInt(20); // สุ่มค่าจาก 0 - 20 print(rd_number); // สำหรับทดสอบ // สร้างลิสรายการใหม่ items = List<String>.generate(rd_number, (i) => 'Item ${i+1}'); }); } @override Widget build(BuildContext context) { print("build"); // สำหรับทดสอบ return Scaffold( appBar: AppBar( title: Text('Home'), ), body: Column( children: [ Container( // สร้างส่วน header ของลิสรายการ padding: const EdgeInsets.all(12.0), decoration: BoxDecoration( color: Colors.teal.withAlpha(100), // borderRadius: BorderRadius.circular(8.0), ), child: Row( children: [ Text('Total ${items.length} items'), ], ), ), Expanded( child: items.length > 0 // กำหนดเงื่อนไขตรงนี้ ? ListView.separated( // กรณีมีรายการ แสดงปกติ itemCount: items.length, itemBuilder: (context, index) { return ListTile( title: Text('${items[index]}'), ); }, separatorBuilder: (BuildContext context, int index) => const Divider(), ) : const Center(child: Text('No items')), // กรณีไม่มีรายการ ), ], ), floatingActionButton: FloatingActionButton(// ปุ่มสำหรับดึงข้อมูลใหม่ onPressed: _refreshData, child: const Icon(Icons.refresh), ), ); } }
ผลลัพธ์ที่ได้

เกี่ยวกับรายละเอียดการใช้งาน ListView สามารถอ่านเพิ่มได้ที่ http://niik.in/957
โค้ดตัวอย่างข้างต้น เราจำลองสร้างข้อมูล List<String> เป็นรายการค่าเริ่มต้น 100 รายการ ในส่วน
ของการใช้งาน เราใช้ ListView.separated เป็นตัวจัดการ มีเงื่อนไขการแสดงข้อมูล ถ้ามีข้อมูลก็แสดง
เป็นลิสรายการ ถ้าไม่มีก็ให้แสดงข้อความตรงกลางว่า 'No items' เรามีปุ่มสำหรับ ทำการ random ค่า
เพื่อสร้างลิสรายการใหม่ ด้านบนของลิสรายการเราก็สร้างส่วน header ของลิสรายการ สำหรับแสดง
จำนวนรายการทั้งหมดที่มี ตัวอย่างการใช้งานข้างต้น เป็นรูปแบบที่เราจะนำไปใช้สำหรับการแสดงข้อมูล
ที่ดึงมาจาก api
เตรียมความพร้อมก่อนใช้งาน Http ดึงข้อมูลจาก Server
เกี่ยวกับการใช้งาน Http ในภาษา Dart หากต้องการรู้รายละเอียดเพิ่มเติม สามารถเข้าไปอ่านได้ที่
ลิ้งค์บทความด้านล่างนี้ อย่างไรก็ตาม ในการใช้งานใน Flutter ก็ไม่มีมีขั้นตอนยุ่งยากนัก
การใช้งาน HTTP Server และ HTTP Client ในภาษา Dart เบื้องต้น http://niik.in/964
https://www.ninenik.com/content.php?arti_id=964 via @ninenik
ติดตั้ง http package
ก่อนจะใช้งาน http เราต้องทำการเพิ่ม http package เข้ามาใช้งานใน flutter โปรเจ็คของเราก่อนโดย
เข้าไปเพิ่มในส่วนของไฟล์ pubspec.yaml แล้วกำหนดในลักษณะดังนี้
dependencies: http: ^0.13.4
ใช้เป็นเวอร์ชั่นล่าสุด เข้าไปดูได้ที่ http package

ในกรณีเขียนโค้ดโดยใช้ VS Code ก็ทำการกดบันทึก ตัวโปรแกรม จะเรียกใช้งานคำสั่ง flutter pub get
เพื่อเพิ่ม package ให้อัตโนมัติ ส่วนกรณีใช้ Android Studio ก็ให้ เรียกใช้คำสั่งผ่าน Terminal ในตัวโปรแกรม
เพิ่อเพิ่ม package เข้ามาในโปรเจ็ค
ทำการ Import http package เข้ามาใช้งาน
import 'package:http/http.dart' as http;
การกำหนดสิทธิ์การขอใช้งานเครือข่าย INTERNET สำหรับ Android
เนื่องจาก app ของเราต้องมีการใช้งาน internet เพราะต้องดึงข้อมูลผ่าน server ให้เราทำการเพิ่มการขอสิทธิ์
การอนุญาตใช้งานในไฟล์ AndroidManifest.xml
อยู่ใน path - android > app > src > main

ให้เรากำหนดค่า ด้านล่างแทรกลงไป
<uses-permission android:name="android.permission.INTERNET" />
ตามรูปแบบดังนี้
<manifest xmlns:android...> ... <uses-permission android:name="android.permission.INTERNET" /> <application ... </manifest>
จัดรูปแบบ Data Model ข้อมูลสำหรับรองรับข้อมูลจาก API
ก่อนที่เราจะดึงข้อมูลมาแสดง เราต้องรู้ก่อนว่าข้อมูลเราเป็นแบบไหน มีโครงสร้างข้อมูลเป้นอย่างไร
ในที่นี้เราจะใช้ข้อมูลจาก https://jsonplaceholder.typicode.com/posts เป็นข้อมูลจำลองหรือ Fake API
สำหรับใช้ทดสอบโดยเฉพาะ
[ { "userId": 1, "id": 1, "title": "sunt aut facere repellat provident occaeenderit", "body": "quia et suscipitnsuscipit recusatecto" } ]
จากรูปแบบข้างต้น เราสามารถกำหนด Data Model สำหรับข้อมูลได้เป็นดังนี้
class Article { final int userId; final int id; final String title; final String body; Article({ required this.userId, required this.id, required this.title, required this.body, }); // ส่วนของ name constructor ที่จะแปลง json string มาเป็น Article object factory Article.fromJson(Map<String, dynamic> json) { return Article( userId: json['userId'], id: json['id'], title: json['title'], body: json['body'], ); } }
เนื้อหาเกี่ยวกับการจัดการข้อมูล JSON สามารถอ่านเพิ่มเติมได้ที่
การใช้งาน JSON String Data ในภาษา Dart เบื้องต้น http://niik.in/963
https://www.ninenik.com/content.php?arti_id=963 via @ninenik
ตอนนี้เราเตรียมส่วนต่างๆ พร้อมแล้วสำหรับการใช้งาน http package ดึงข้อมูล api มาแสดง
เรียกใช้งาน Http package เพื่อดึงข้อมูล API มาแสดง
มาถึงขั้นตอนการใช้งาน http package เราจะทำการสร้างฟังก์ชั่น ที่จะทำการดึงข้อมูล api มาแสดง
มีรูปแบบการใช้งานไม่ยุ่งยาก ซึ่ง flutter ก็มีเครื่องมาให้ และเราก็ควรใช้งาน นี่คือส่วน package ที่เราจะใช้
ในหน้าดึงข้อมูล
import 'dart:async'; // สำหรับจัดการข้อมูลแบบ async import 'dart:convert'; // สำหรับจัดการข้อมูล JSON data import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart'; // มีคำสั่งสำหรับจัดการข้อมูลอยู่ background import 'package:http/http.dart' as http; // ดึงข้อมูลจัดการข้อมูลบนเครือข่าย internet
ปกติเราสามารถกำหนดคำสั่งจัดการกับข้อมูล JSON ได้อยู่แล้ว แต่ก็อาจจะไม่ครอบคลุม ถ้าข้อมูลนั้นๆ มีขนาด
ที่ค่อนข้างใหญ่ หรือมีหลายรายการ การใช้ตัวช่วยของ flutter จะทำให้สามารถแปลงข้อมูลที่มีจำนวนมากๆ
โดยทำงานอยู่เบื้องหลังให้เรา
มาดูการกำหนดฟังก์ชั่นสำหรับดึงข้อมูล api ด้วย http package และการแปลงข้อมูล api ที่ได้มาในรูป
แบบ JSON data เป็นในรูปแบบ List<Article> โดยใช้ฟังก์ชั่นของ Flutter มาช่วย
// สรัางฟังก์ชั่นดึงข้อมูล คืนค่ากลับมาเป็นข้อมูล Future ประเภท List ของ Article Future<List<Article>> fetchArticle() async { // ทำการดึงข้อมูลจาก server ตาม url ที่กำหนด final response = await http .get(Uri.parse('https://jsonplaceholder.typicode.com/posts')); // เมื่อมีข้อมูลกลับมา if (response.statusCode == 200) { // ส่งข้อมูลที่เป็น JSON String data ไปทำการแปลง เป็นข้อมูล List<Article // โดยใช้คำสั่ง compute ทำงานเบื้องหลัง เรียกใช้ฟังก์ชั่นชื่อ parseArticles // ส่งข้อมูล JSON String data ผ่านตัวแปร response.body return compute(parseArticles, response.body); } else { // กรณี error throw Exception('Failed to load article'); } } // ฟังก์ชั่นแปลงข้อมูล JSON String data เป็น เป็นข้อมูล List<Article> List<Article> parseArticles(String responseBody) { final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>(); return parsed.map<Article>((json) => Article.fromJson(json)).toList(); }
จะมีอยู่สองฟังก์ชั่น คือ ฟังก์ชั่นแรกทำการดึงข้อมูลให้ได้ข้อมูล JSON String data มาแล้ว
ส่งต่อมาอีกฟังก์ชั่น เพื่อแปลงเป็น List<Article> โดยใช้คำสั่ง compute() ที่ทำงานเบื้องหลัง
จะมีประโยชน์มากๆ กรณีที่ข้อมูลนั้นๆ มีขนาดใหญ่
เมื่อเราได้รูปแบบข้อมูล ได้คำสั่งดึงข้อมูล มาเรียบร้อยแล้ว ต่อไปก็เป็นส่วนของการนำไปแสดง
หรือใช้งานร่วมกับ FutureBuilder
// กำนหดตัวแปรข้อมูล articles late Future<List<Article>> articles;
เรากำหนดตัวแปรชื่อ articles เป็นข้อมูล Future<List<Article>> ใช้ keyword late เพื่อป้องกัน
กรณีเกิด null safety ประมาณว่า ข้อมูลนี้จะไม่เป็น null แน่นอน แต่ข้อมูลจะมาช้าหน่อย เหมือนสัญญาไว้
และจะทำตามสัญญา (late มาจาก lazy)
เราจะมากำหนดค่าใน initState() ดังนี้
@override void initState() { print("initState"); // สำหรับทดสอบ super.initState(); articles = fetchArticle(); // ทำตามสัญญา กำหนดค่า โดยให้ไปดึงจากฟังก์ชั่น }
สร้างฟังก์ชั่นสำหรับดึงข้อมูลซ้ำ หรือโหลดข้อมูลใหม่
void _refreshData(){ setState(() { print("setState"); // สำหรับทดสอบ articles = fetchArticle(); // โหลดข้อมูลใหม่ }); }
และสุดท้ายก็ส่วนของการประยุกต์ใช้งาน FutureBuilder กับ ListView
@override Widget build(BuildContext context) { print("build"); // สำหรับทดสอบ return Scaffold( appBar: AppBar( title: Text('Home'), ), body: Center( child: FutureBuilder<List<Article>>( // ชนิดของข้อมูล future: articles, // ข้อมูล Future builder: (context, snapshot) { print("builder"); // สำหรับทดสอบ print(snapshot.connectionState); // สำหรับทดสอบ if (snapshot.hasData) {// กรณีมีข้อมูล return Column( children: [ Container( // สร้างส่วน header ของลิสรายการ padding: const EdgeInsets.all(5.0), decoration: BoxDecoration( color: Colors.teal.withAlpha(100), ), child: Row( children: [ Text('Total ${snapshot.data!.length} items'), // แสดงจำนวนรายการ ], ), ), Expanded( // ส่วนของลิสรายการ child: snapshot.data!.length > 0 // กำหนดเงื่อนไขตรงนี้ ? ListView.separated( // กรณีมีรายการ แสดงปกติ itemCount: snapshot.data!.length, itemBuilder: (context, index) { return ListTile( title: Text(snapshot.data![index].title), ); }, separatorBuilder: (BuildContext context, int index) => const Divider(), ) : const Center(child: Text('No items')), // กรณีไม่มีรายการ ), ], ); } else if (snapshot.hasError) { // กรณี error return Text('${snapshot.error}'); } // กรณีสถานะเป็น waiting ยังไม่มีข้อมูล แสดงตัว loading return const CircularProgressIndicator(); }, ), ), floatingActionButton: FloatingActionButton( // ปุ่มทดสอบสำหรับดึงข้อมูลซ้ำ onPressed: _refreshData, child: const Icon(Icons.refresh), ), ); }
เมื่อเราใช้งาน FutureBuilder ข้อมูลสุดท้ายของเราก็คือ snapshot.data เป็นข้อมูลในรูปแบบ
List<Article> หรือก็คือ อาเรย์ของ Article object ดังนั้นเวลาเราเรียกใช้งาน เมื่อวนลูปแสดงใน ListView
กฺ็สามารถอ้างอิงได้จากค่า index เช่น เราต้องการแสดง title ก็จะใช้เป็น
snapshot.data![index].title
สังเกตว่าหลัง snapshot.data มีเครื่องหมาย ! กำกับไว้ ก็เกี่ยวกับ null safety อีกเหมือนเคย เป็นการบอกว่า
ข้อมูล snapshot.data จะไม่เป็น null เมื่อไม่เป้น null การเรียกใช้งาน ก็จะเรียกใช้งานได้
เราจะได้ไฟล์ home.dart เป็นดังนี้
import 'dart:async'; import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart'; import 'package:http/http.dart' as http; 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> { // กำนหดตัวแปรข้อมูล articles late Future<List<Article>> articles; @override void initState() { print("initState"); // สำหรับทดสอบ super.initState(); articles = fetchArticle(); } void _refreshData(){ setState(() { print("setState"); // สำหรับทดสอบ articles = fetchArticle(); }); } @override Widget build(BuildContext context) { print("build"); // สำหรับทดสอบ return Scaffold( appBar: AppBar( title: Text('Home'), ), body: Center( child: FutureBuilder<List<Article>>( // ชนิดของข้อมูล future: articles, // ข้อมูล Future builder: (context, snapshot) { print("builder"); // สำหรับทดสอบ print(snapshot.connectionState); // สำหรับทดสอบ if (snapshot.hasData) {// กรณีมีข้อมูล return Column( children: [ Container( // สร้างส่วน header ของลิสรายการ padding: const EdgeInsets.all(5.0), decoration: BoxDecoration( color: Colors.teal.withAlpha(100), ), child: Row( children: [ Text('Total ${snapshot.data!.length} items'), // แสดงจำนวนรายการ ], ), ), Expanded( // ส่วนของลิสรายการ child: snapshot.data!.length > 0 // กำหนดเงื่อนไขตรงนี้ ? ListView.separated( // กรณีมีรายการ แสดงปกติ itemCount: snapshot.data!.length, itemBuilder: (context, index) { return ListTile( title: Text(snapshot.data![index].title), ); }, separatorBuilder: (BuildContext context, int index) => const Divider(), ) : const Center(child: Text('No items')), // กรณีไม่มีรายการ ), ], ); } else if (snapshot.hasError) { // กรณี error return Text('${snapshot.error}'); } // กรณีสถานะเป็น waiting ยังไม่มีข้อมูล แสดงตัว loading return const CircularProgressIndicator(); }, ), ), floatingActionButton: FloatingActionButton( // ปุ่มทดสอบสำหรับดึงข้อมูลซ้ำ onPressed: _refreshData, child: const Icon(Icons.refresh), ), ); } } // สรัางฟังก์ชั่นดึงข้อมูล คืนค่ากลับมาเป็นข้อมูล Future ประเภท List ของ Article Future<List<Article>> fetchArticle() async { // ทำการดึงข้อมูลจาก server ตาม url ที่กำหนด final response = await http .get(Uri.parse('https://jsonplaceholder.typicode.com/posts')); // เมื่อมีข้อมูลกลับมา if (response.statusCode == 200) { // ส่งข้อมูลที่เป็น JSON String data ไปทำการแปลง เป็นข้อมูล List<Article // โดยใช้คำสั่ง compute ทำงานเบื้องหลัง เรียกใช้ฟังก์ชั่นชื่อ parseArticles // ส่งข้อมูล JSON String data ผ่านตัวแปร response.body return compute(parseArticles, response.body); } else { // กรณี error throw Exception('Failed to load article'); } } // ฟังก์ชั่นแปลงข้อมูล JSON String data เป็น เป็นข้อมูล List<Article> List<Article> parseArticles(String responseBody) { final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>(); return parsed.map<Article>((json) => Article.fromJson(json)).toList(); } // Data models class Article { final int userId; final int id; final String title; final String body; Article({ required this.userId, required this.id, required this.title, required this.body, }); // ส่วนของ name constructor ที่จะแปลง json string มาเป็น Article object factory Article.fromJson(Map<String, dynamic> json) { return Article( userId: json['userId'], id: json['id'], title: json['title'], body: json['body'], ); } }
ผลลัพธ์ที่ได้

เริ่มต้นเราอยู่ที่หน้า About เมื่อมาที่หน้า Home ก็จะทำการโหลดข้อมูลจาก API ขณะโหลด
ก็จะขึ้นตัว loading เพราะต้นนี้ยังไม่มีข้อมูล และเมื่อโหลดข้อมูลเสร็จเรียบร้อยแล้ว ก็แสดงข้อมูลใน
ลิสรายการด้วย ListView พอเรากดที่ปุ่ม refresh ก็จะทำการโหลดข้อมูลใหม่อีกครั้ง แต่ด้วยรูปแบบ
การกำหนดเงื่อนไขข้างต้น เราตรวจสอบโดยใช้
if (snapshot.hasData){
เมื่อเรากด refresh ค่า snapshot.hasData เดิมยังเเป็น true เพราะมีข้อมูลเก่าแสดงอยู่ทำให้
ไม่ขึ้นตัว loading ใหม่อีกครั้ง ดังนั้น ถ้าเราต้องการให้ขึ้นตัว loading อีกครั้ง เมื่อกำลังโหลดใหม่
ให้เราใส่การตรวจสอบสถานะการเชื่อมต่อเพิ่มเข้าไปด้วย เป็นดังนี้
// มีข้อมูล และต้องเป็น done ถึงจะแสดงข้อมูล ถ้าไม่ใช่ ก็แสดงตัว loading if (snapshot.hasData && snapshot.connectionState == ConnectionState.done) {
เมื่อกำหนดในรูปแบบข้างต้นแล้ว เวลาเรารีเฟรสหรือดึงข้อมูลใหม่ ถึงตัว snapshot.hasData จะเป็น true
แต่ค่า snapshot.connectionState จะเป็น waiting ดังนั้นตัว loading จึงทำการแสดงอีกครั้ง แล้วค่อย
แสดงข้อมูลที่ดึงมา เมื่อได้รับข้อมูลสุดท้าย
ผลลัพธ์ที่ได้

เกี่ยวกับการใช้งาน http package ในเบื้องต้นก็จะมีเท่านี้ แต่เรายังจะมีเนื้อหาเกี่ยวกับการใช้งานเรื่องนี้อีก
เช่น การเพิ่ม ลบ แก้ไข หรือแสดงข้อมูล
หวังว่าเนื้อหานี้จะเป็นแนวทางสำหรับนำไปประยุกต์ใช้งานต่อไป บทความหน้าจะเป็นอะไร รอติดตาม
เพิ่มเติมเนื้อหา ครั้งที่ 1 วันที่ 25-10-2021
แนวทางการกำหนด Data Model สำหรับใช้งานข้อมูล
เมื่อเรารู้โครงสร้างข้อมูลของ JSON String data แล้ว เราสามารถนำมาเป็นแนวทาง
ในการกำหนดรูปแบบของ Data Model เพื่อใช้งานได้ สมมติโครงสร้างข้อมูลที่ได้จาก API
มีรูปแบบ JSON String data ดังนี้
[ { "userId": 1, "id": 1, "title": "sunt aut facere repellat provident occaeenderit", "body": "quia et suscipitnsuscipit recusatecto" } ]
เราจะมากำหนด Data Model ในรูปแบบดังนี้
// กำหนด ชื่อ class class Classname{ // กำหนด state หรือ property ของ class // กำหนด parameter contructor // กำนหนด factory constructor }
สมมติเราจะใช้ชื่อว่าคลาสว่า News และมี property อันเดียวคือ id เป็น ก็จะได้เป็น
// กำหนด ชื่อ class class News{ // กำหนด state หรือ property ของ class final String id; // กำหนด parameter contructor News({ required this.id }); // กำนหนด factory constructor factory News.fromJson(Map<String, dynamic> json) { return News( id: json['id'], ); } }
โครงสร้างข้อมูล JSON String data ของเรามีด้วยกัน 4 ตัวคือ userID , id , title และ body
เวลาเราสร้าง Data Model ไม่จำเป้นต้องใช้หมดทั้ง 4 ก็ได้ อาจจะกำหนดแค่ id กับ title เพื่อใช้
งานก็ได้
สมมติเราเพิ่มส่วนของ title และ body เพิ่มลงไป ก็จะได้เป็นดังนี้
// กำหนด ชื่อ class class News{ // กำหนด state หรือ property ของ class final String id; final String title; final String description; // กำหนด parameter contructor News({ required this.id, required this.title, required this.description }); // กำนหนด factory constructor factory News.fromJson(Map<String, dynamic> json) { return News( id: json['id'], title: json['title'], description: json['body'], ); } }
สังเกตว่าข้อมูลส่วนของ body เรากำหนดชื่อใหม่ เพื่อให้เข้าใจมากขึ้น โดยใช้เป็น description
เราจะต้องเปลี่ยนส่วนที่เหลือเป็น description ทั้งใน parameter contructor และ factory constructor
ยกเว้นส่วนที่อ้างอิงจาก JSON เราต้องใช้เป็นค่าเดิม
description: json['body'], //ค่า description ต้องมาจาก body
ต่อไป สมมติเรามั่นใจว่าข้อมูล JSON ค่าส่วนของ id และ title ยังไงก็จะมีค่าแน่นอน ไม่เป็นค่าว่าง แต่
ส่วนของ body อาจจะเป็นค่าว่างได้ ดังนั้น เราต้องป้องกันการเกิด null safety หรือ การเรียกใช้งานค่า null
// กำหนด ชื่อ class class News{ // กำหนด state หรือ property ของ class final String id; final String title; final String? description; // กำหนด parameter contructor News({ required this.id, required this.title, this.description }); // กำนหนด factory constructor factory News.fromJson(Map<String, dynamic> json) { return News( id: json['id'], title: json['title'], description: json['body'], ); } }
ส่วนของการกำหนด property ให้เราใส่ ? ต่อเข้าไปในชนิดข้อมูล ของรายการที่จะป้องกัน
final String? description;
และในส่วนของ parameter constructor ก็เอาคำว่า required ออก เพื่อเป็นการบอกว่า ค่านี้จะมี
หรือไม่ก็ได้ ดังนั้นเมื่อกำหนดในลักษณะนี้ ตัว description ก็มีโอกาสเป็นค่า null ได้ เวลาเรียกใช้งาน
เช่นดึงมาแสดงผ่านข้อมูล snapshot เราก็ต้องใส่เครื่องหมาย ! ต่อท้ายเพื่อบอกว่า ข้อมูลที่เรียกใช้นี้
อาจจะเป็น null ได้
snapshot.data![index].description!;
เกี่ยวกับการใช้งาน class ดูเพิ่มเติมได้ที่ http://niik.in/942
กด Like หรือ Share เป็นกำลังใจ ให้มีบทความใหม่ๆ เรื่อยๆ น่ะครับ

อ่านต่อที่บทความ
-
27 Oct2021การใช้งาน Card Widget ร่วมกับ ListView ใน Flutter อ่าน 5,003
เนื้อหาตอนต่อไปนี้ จะมาดูเกี่ยวกับ widget เล็กๆ ที่จะมาช่วย ให้การแสดงผลใ
เนื้อหาที่เกี่ยวข้อง
-
04 Dec2019การใช้งาน Stateless และ Stateful Widget ใน Flutter เบื้องต้น อ่าน 24,022
เนื้อหาตอนที่แล้ว เราได้ทำการสร้าง App เริ่มต้น โดยใช้งาน widget มาประกอบ
-
06 Dec2019แนะนำ Basic Widget ที่ควรรู้สำหรับใช้งาน Flutter เบื้องต้น อ่าน 19,114
เนื้อหาตอนที่แล้ว เราได้ทำความเข้าใจเบื้องต้นเกี่ยวกับ การใช้งาน Stateles
-
07 Dec2019การติดตั้งและใช้งาน Package ภายนอก ใน Flutter เบื้องต้น อ่าน 9,081
เนื้อหาตอนต่อไปนี้ เราจะมาดูเกี่ยวกับการติดตั้ง Package จาก ภายนอก เพื่อม
-
09 Dec2019การกำหนด และใช้งาน ListView Widget ใน Flutter เบื้องต้น อ่าน 14,301
ต่อจากตอนที่แล้ว ที่เราได้ใช้งาน Package จากภายนอก สำหรับสร้าง random wor
-
12 Dec2019การใช้งาน Navigator และ Routing ใน Flutter เบื้องต้น อ่าน 16,056
ก่อนที่เราจะเข้าสู่เนื้อหาการประยุกต์ต่อจากตอนที่แล้ว เนื่้องจาก สิ่งที่เ
-
15 Dec2019การใช้งาน Theme และรู้จักกับ InheritedWidget ใน Flutter อ่าน 8,052
ก่อนที่เราจะไปประยุกต์การใช้งาน Theme กับโปรเจ็คจาก เนื้อหาบทความของตอนที
-
17 Dec2019การใช้งาน Drawer กำหนด SideMenu ใน Flutter เบื้องต้น อ่าน 12,105
เนื้อหาตอนต่อไปนี้ เราจะมาประยุกต์ใช้งาน Drawer ในโปรเจ็ค App ของเราต่อ จ
-
18 Dec2019การใช้งาน BottomNavigationBar ใน Flutter เบื้องต้น อ่าน 16,015
ในตอนที่แล้ว เราได้รู้จัก การใช้งาน Drawer หรือที่เรียกว่า SideMenu เบื้อ
-
21 Oct2021แสดงข้อความด้านล่างหน้าจอด้วย SnackBar ใน flutter อ่าน 2,038
SnackBar เป็น widget ที่เราสามารถใช้สำหรับแสดง popup ข้อความ แ
-
22 Oct2021การกำหนดเพิ่ม Fonts เพื่อใช้งานใน App ของ Flutter อ่าน 2,959
เนื้อหานี้จะมาแนะนำแนวทางการเพิ่มฟอนท์สำหรับ ใช้งานใน app กรณีเราอยากได้ร
-
23 Oct2021จัดการ Tab ด้วย TabController ใน Flutter อ่าน 5,313
เนื้อหานี้มาดูเกี่ยวกับการใช้งาน tab ใน flutter ซึ่งเป็นรูปแบบ การใช้งานท
-
24 Oct2021การใช้งาน FutureBuilder ที่เป็น Async widgets ใน Flutter อ่าน 4,168
เนื้อหาตอนต่อไปนี้ จะมาดูเกี่ยวกับการใช้งาน async widgets ที่ชื่อว่า Futu
-
25 Oct2021การใช้งาน StreamBuilder จัดการข้อมูล Stream ใน Flutter อ่าน 3,607
ในตอนที่แล้วเรารู้จักกับ FutureBuilder ซึ่งเป็น async widgets หนึ่งใน Flu
-
กำลังอ่านเนื้อหานี้อยู่26 Oct2021การใช้งาน Http ดึงข้อมูลจาก Server มาแสดงใน Flutter อ่าน 7,453
เนื้อหาตอนต่อไปนี้ เราจะมาดูเกี่ยวกับวิธีการดึงข้อมูลจาก Server ที่เป็นข้
-
27 Oct2021การใช้งาน Card Widget ร่วมกับ ListView ใน Flutter อ่าน 5,003
เนื้อหาตอนต่อไปนี้ จะมาดูเกี่ยวกับ widget เล็กๆ ที่จะมาช่วย ให้การแสดงผลใ
URL สำหรับอ้างอิง
Top
Copy
ขอบคุณทุกการสนับสนุน
![]()