สร้าง Project
เริ่มต้นสร้าง Flutter project ชื่อ tripbooking (project ตัวอย่าง) กันก่อนเลย โดยการรันคำสั่งสร้าง project และเปิด vscode ที่ folder นั้น
flutter create tripbooking
cd tripbooking
code .
สร้าง folder ที่จะเอาไว้เก็บไฟล์ต่างๆให้เป็นระเบียบ โดยในที่นี่ขึ้นอยู่กับความเหมาะสม สำหรับที่จะแนะนำให้สร้าง folder ทั้งหมด 3 folder คือ
- page = เอาไว้เก็บหน้าต่างๆ ของ application
- service = ส่วนประมวลผลเรียก Api
- model = สำหรับเก็บ database model
เพิ่ม libraries ที่เกี่ยวข้องกับ project
flutter pub add retrofit
flutter pub add retrofit_generator
flutter pub add json_serializable
flutter pub add build_runner --dev
flutter pub add dio
flutter pub add provider
flutter pub add get
flutter pub add get_storage
สร้าง Provider ไว้จัดการข้อมูลที่ใช้ใน Application
- สร้าง Folder ย่อยชื่อ provider ภายใน folder service
- สร้างไฟล์ของ provider ชื่อ appdata.dart
ในไฟล์ appdata.dart สร้างตัวแปล baseUrl ของ api ที่ application เราต้องติดต่อ ตามตัวอย่าง
import 'package:flutter/material.dart';
class AppData with ChangeNotifier {
//Api baseurl
String baseurl = "http://192.168.1.100:8888";
}
ไปที่ main.dart แก้ Code ใน main() เพื่อใช้งาน provider ที่สร้างขึ้น
void main() {
runApp(MultiProvider(providers: [
ChangeNotifierProvider(
create: (context) => AppData(),
)
], child: const MyApp()));
}
เรียบร้อยเรามี provider ไว้ใช้งานใน application เราแล้ว
สร้าง RestClient โดยใช้ Retrofit
ตัวเรียก api ในที่นี้เราจะเรียกว่า service เป็นไฟล์ที่เก็บใน folder service ซึ่งเราจะแยกตาม path (url) ของ restful api เช่น จะเรียกใช้งาน api ที่มี path เป็น /destination เราก็จะสร้างไฟล์ชื่อ destination.dart
สร้างไฟล์ destination.dart ใน folder service
import 'package:retrofit/retrofit.dart';
import 'package:dio/dio.dart';
import 'package:tripbooking/model/destination.dart';
part 'destination.g.dart';
@RestApi()
abstract class DestinationService {
factory DestinationService(Dio dio, {String baseUrl}) = _DestinationService;
}
ซึ่งเมื่อพิมพ์คำสั่งเสร็จแล้วมันจะ Error ซึ่งถูกแล้ว เพราะว่า Retrofit ต้องมีการ generate คำสั่งใหม่ของมัน (https://pub.dev/packages/retrofit) เป็นไฟล์ชื่อ destination.g.dart ตามที่เราระบุ
เปิด terminal แล้วพิมพ์คำสั่งให้ retrofit generate ไฟล์
flutter pub run build_runner watch
มันจะ generate ไฟล์แล้วเปิดค้างรอ ถ้าเราแก้ไขไฟล์มันก็จะ auto generate ใหม่ ถ้าจะยกเลิก ก็กด Ctrl+C หรือเราสามารถ ใช้คำสั่ง flutter pub run build_runner build (ใช้ option build) ก็ได้ มันจะ generate ครั้งเดียว ถ้าแก้ไฟล์ ต้องมาสั่ง generate ใหม่เอง
ไฟล์ที่ generate ขึ้นเราไม่แก้ไขมัน เพราะมันจะถูกลบแล้วถูกสร้างใหม่ตลอด
ตอนนี้จะมี Retrofit client (service) ที่ใช้ติดต่อไปยัง api แล้ว ต่อไปจะเป็นการสร้าง method ในการเรียก api แต่จะเรียก api ได้ ต้องมี model มารับข้อมูลที่ได้คืนมาจาก api ด้วยด้วย ดังนั้น ต้องสร้าง model ก่อน
- สร้างไฟล์ destination.dart ใน folder model
- เข้าเวบ https://app.quicktype.io แล้วก็เอา json ที่ได้จาก api มาวางเพื่อให้เวบมันสร้าง class ของ dart ให้ตามรูปตัวอย่าง
- ตั้งชื่อ class เป็น Destination (เพราะเป็นข้อมูลที่ได้จากการเรียก api destination)
- วาง json ได้มา ลงไป
- เลือกภาษาเป็น Dart
- เลือกตัวเลือกแค่ตัวเดียวคือ Make all properties required
- กด copy code
กลับไปที่ไฟล์ destination.dart ใน model แล้ววาง code ลงไป แต่ใน flutter จะ Error เพราะ @required ให้ลง @ ออก
ตอนนี้ เราก็จะมี model ไว้รับข้อมูลจาก api แล้ว
กลับไปที่ไฟล์ destination.dart ใน folder service (retrofit) แล้วเขียน คำสั่งเพิ่มเพื่อสร้าง method ในการเรียก api
abstract class DestinationService {
factory DestinationService(Dio dio, {String baseUrl}) = _DestinationService;
@GET("/destination")
Future<List<Destination>> getDestinations();
}
จะเป็นการเรียกไปยัง path /destination และจะได้ผลลัพธ์ออกมาเป็น List ของ Destination (mode ที่เราเพิ่งสร้าง) นั่นเอง เมื่อ save ตัว retrofit จะ generate ไฟล์ให้ (ถ้าเรายังสั่งเป็น watch อยู่) หรือสั่ง build เพื่อ generate ใหม่อีกครั้ง
เรียบร้อย เราสร้างตัว service ที่เอาไว้เรียก api ได้แล้ว
อ่านเพิ่มเติมรูปแบบการใช้ retrofit ที่ (https://pub.dev/packages/retrofit)
เรียกใช้งาน service ที่เราสร้าง
ตัวอย่างเช่น เราสร้างหน้า home.dart ใน folder page ในรูปแบบ FutureBuilder
import 'dart:convert';
import 'dart:developer';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:tripbooking/model/destination.dart';
import 'package:tripbooking/service/destination.dart';
import 'package:provider/provider.dart';
import 'package:tripbooking/service/provider/appdata.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
// 1. กำหนดตัวแปร
List<Destination> destinations = [];
late Future<void> loadDataMethod;
late DestinationService destinationService;
// 2. สร้าง initState เพื่อสร้าง object ของ service
// และ async method ที่จะใช้กับ FutureBuilder
@override
void initState() {
super.initState();
// 2.1 object ของ service โดยต้องส่ง baseUrl (จาก provider) เข้าไปด้วย
destinationService =
DestinationService(Dio(), baseUrl: context.read<AppData>().baseurl);
// 2.2 async method
loadDataMethod = loadData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Home Page'),
),
// 3. เรียก service ในรูปแบบของ FutureBuilder (หรือจะไม่ใช้ก็ได้ แค่ตัวอย่างให้ดูเฉยๆ)
body: FutureBuilder(
future: loadDataMethod, // 3.1 object ของ async method
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Center(child: Text(jsonEncode(destinations)));
} else {
return const Center(child: CircularProgressIndicator());
}
}),
);
}
// 4. Async method ที่เรียก service เมื่อได้ข้อมูลก็เอาไปเก็บไว้ที่ destinations ที่ประกาศไว้ด้านบนเป็น List
Future<void> loadData() async {
try {
destinations = await destinationService.getDestinations();
} catch (err) {
log('Error: $err');
}
}
}
เท่านี้ เราก็เรียกใช้ service ได้อย่างง่ายๆ
แต่ปัญหาคือต้องฝึกดูเวลามันผิดพลาด เกิด Error ตอนเรียก service มันจะต้องใช้ try catch จับ ตามตัวอย่าง
Top comments (0)