ตอนที่ 7 ทำแอพ Flutter : ระบบเครือข่าย (Networking) และข้อมูล

  1. คำขอ HTTP ใน Flutter
  2. JSON Serialization และ Deserialization
  3. ทำงานกับ REST APIs
  4. การรวม (Integration) GraphQL

ในโลกปัจจุบันที่เชื่อมต่อถึงกัน การทำแอพมือถือมักอาศัยแหล่งข้อมูลภายนอกเพื่อจัดหาเนื้อหาที่สมบูรณ์และไดนามิก API (Application Programming Interfaces) มีบทบาทสำคัญในการเปิดใช้งานการสื่อสารระหว่างการทำแอพ Flutter และเซิร์ฟเวอร์ส่วนหลัง ทำให้สามารถดึงข้อมูล ส่ง และอัปเดตข้อมูลได้อย่างราบรื่น JSON (JavaScript Object Notation) เป็นรูปแบบการแลกเปลี่ยนข้อมูลที่มีน้ำหนักเบายอดนิยมที่ใช้สำหรับการรับส่งข้อมูลระหว่างไคลเอ็นต์และเซิร์ฟเวอร์ในการทำแอพ

ในบทความนี้ เราจะสำรวจวิธีสร้างคำขอ HTTP ทำงานกับข้อมูล JSON และรวมเข้ากับ REST และ GraphQL API ในการทำแอพ Flutter ของคุณ ดำดิ่งสู่โลกแห่งเครือข่ายและการจัดการข้อมูลในการทำแอพ Flutter

1. คำขอ HTTP ใน Flutter

Flutter ให้บริการแพ็คเกจ ‘http’ เพื่ออำนวยความสะดวกในการร้องขอ HTTP ขั้นแรก เพิ่มแพ็คเกจ http ลงในไฟล์ ‘pubspec.yaml’ ของคุณ:

dependencies:
  http: ^0.13.3

หลังจากนั้น ให้นำเข้าแพ็คเกจในไฟล์ Dart ของคุณ:

import 'package:http/http.dart' as http;

หากต้องการขอ GET อย่างง่าย ให้ใช้วิธี ‘http.get()’:

Future<void> fetchData() async {
  final response = await http.get('https://api.example.com/data');
  if (response.statusCode == 200) {
    // Handle the received data
  } else {
    // Handle the error
  }
}

สำหรับเมธอด HTTP อื่นๆ เช่น POST, PUT, DELETE ให้ใช้ฟังก์ชันที่เกี่ยวข้อง: ‘http.post()’, ‘http.put()’ และ ‘http.delete()’ หากต้องการส่งข้อมูลในเนื้อหาคำขอ ให้รวมไว้เป็นพารามิเตอร์ ‘body’

2. JSON Serialization และ Deserialization

หากต้องการทำงานกับข้อมูล JSON ใน Dart ให้ใช้ไลบรารี ‘dart:convert’:

import 'dart:convert';

ในการแปลงสตริง JSON เป็นวัตถุ Dart ให้ใช้ฟังก์ชัน ‘jsonDecode()’:

String jsonString = '{"name": "John", "age": 30}';
Map<String, dynamic> user = jsonDecode(jsonString);

หากต้องการแปลงวัตถุ Dart เป็นสตริง JSON ให้ใช้ฟังก์ชัน ‘jsonEncode()’:

Map<String, dynamic> user = {'name': 'John', 'age': 30};
String jsonString = jsonEncode(user);

สำหรับโครงสร้าง JSON ที่ซับซ้อนมากขึ้น ให้พิจารณาใช้ไลบรารีการสร้างโค้ด เช่น ‘json_serializable’

3. ทำงานกับ REST APIs

REST (Representational State Transfer) APIs ใช้กันอย่างแพร่หลายสำหรับการสื่อสารระหว่างไคลเอ็นต์และเซิร์ฟเวอร์ API เหล่านี้เป็นไปตามชุดกฎและข้อตกลงที่เป็นมาตรฐาน ทำให้ง่ายต่อการทำงาน

หากต้องการดึงข้อมูลจาก REST API ขั้นแรก ให้ส่งคำขอ GET ไปยังปลายทาง จากนั้นแยกวิเคราะห์การตอบสนอง JSON:

Future<List<dynamic>> fetchPosts() async {
  final response = await http.get('https://jsonplaceholder.typicode.com/posts');
  if (response.statusCode == 200) {
    List<dynamic> jsonData = jsonDecode(response.body);
    return jsonData;
  } else {
    throw Exception('Failed to load data');
  }
}

หากต้องการส่งข้อมูลไปยัง REST API ให้ส่งคำขอ POST และรวมข้อมูลเป็นเนื้อหาคำขอ:

Future<void> createPost(Map<String, dynamic> post) async {
  final response = await http.post(
    'https://jsonplaceholder.typicode.com/posts',
    headers: {'Content-Type': 'application/json; charset=UTF-8'},
    body: jsonEncode(post),
  );

  if (response.statusCode == 201) {
    // Handle success
  } else {
    // Handle error
  }
}

ในทำนองเดียวกัน คุณสามารถอัปเดตและลบข้อมูลโดยใช้คำขอ PUT และ DELETE:

Future<void> updatePost(int postId, Map<String, dynamic> updatedPost) async {
  final response = await http.put(
    'https://jsonplaceholder.typicode.com/posts/$postId',
    headers: {'Content-Type': 'application/json; charset=UTF-8'},
    body: jsonEncode(updatedPost),
  );

  if (response.statusCode == 200) {
    // Handle success
  } else {
    // Handle error
  }
}

Future<void> deletePost(int postId) async {
  final response = await http.delete('https://jsonplaceholder.typicode.com/posts/$postId');

  if (response.statusCode == 200) {
    // Handle success
  } else {
    // Handle error
  }
}


ลบข้อมูลโดยใช้คำขอ PUT และ DELETE:

โผคัดลอกรหัสFuture<void> updatePost(int postId, Map<String, dynamic> updatedPost) async {
  final response = await http.put(
    'https://jsonplaceholder.typicode.com/posts/$postId',
    headers: {'Content-Type': 'application/json; charset=UTF-8'},
    body: jsonEncode(updatedPost),
  );

  if (response.statusCode == 200) {
    // Handle success
  } else {
    // Handle error
  }
}

Future<void> deletePost(int postId) async {
  final response = await http.delete('https://jsonplaceholder.typicode.com/posts/$postId');

  if (response.statusCode == 200) {
    // Handle success
  } else {
    // Handle error
  }
}

ตรวจสอบให้แน่ใจว่าได้จัดการข้อยกเว้นและข้อผิดพลาดอย่างเหมาะสม โดยให้ข้อเสนอแนะแก่ผู้ใช้เมื่อจำเป็น

4. การรวม (Integration) GraphQL

GraphQL เป็นภาษาเคียวรีที่มีประสิทธิภาพสำหรับ API ที่มอบความยืดหยุ่นและการควบคุมการดึงข้อมูลและการจัดการข้อมูล หากต้องการทำงานกับ GraphQL ใน Flutter ให้ใช้แพ็คเกจ ‘graphql_flutter’:

dependencies:
  graphql_flutter: ^5.0.0

จากนั้น สร้างไคลเอ็นต์ GraphQL ในแอพของคุณ:

import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';

ValueNotifier<GraphQLClient> clientFor({
  required String uri,
  String? subscriptionUri,
}) {
  final httpLink = HttpLink(uri);

  Link link = httpLink;
  if (subscriptionUri != null) {
    final websocketLink = WebSocketLink(subscriptionUri);
    link = Link.split((request) => request.isSubscription, websocketLink, httpLink);
  }

  return ValueNotifier(
    GraphQLClient(
      cache: GraphQLCache(),
      link: link,
    ),
  );
}

void main() {
  final client = clientFor(
    uri: 'https://api.example.com/graphql',
    subscriptionUri: 'wss://api.example.com/graphql',
  );

  runApp(
    MaterialApp(
      home: MyApp(),
      builder: (context, child) {
        return GraphQLProvider(
          client: client,
          child: child,
        );
      },
    ),
  );
}

ตอนนี้ คุณสามารถใช้วิดเจ็ต ‘Query’ และ ‘Mutation’ ที่มีให้โดยแพ็คเกจเพื่อทำการสืบค้นและการกลายพันธุ์:

import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('GraphQL Example')),
      body: Query(
        options: QueryOptions(
          document: gql('''
            query GetPosts {
              posts {
                id
                title
                content
              }
            }
          '''),
        ),
        builder: (QueryResult result, {refetch, FetchMore? fetchMore}) {
          if (result.isLoading) {
            return CircularProgressIndicator();
          }

          if (result.hasException) {
            return Text('Error: ${result.exception}');
          }

          final posts = result.data!['posts'];
          return ListView.builder(
            itemCount: posts.length,
            itemBuilder: (context, index) {
              final post = posts[index];
              return ListTile(
                title: Text(post['title']),
                subtitle: Text(post['content']),
              );
            },
          );
        },
      ),
    );
  }
}

ในบทความนี้ เราได้สำรวจวิธีสร้างคำขอ HTTP ทำงานกับข้อมูล JSON และรวมเข้ากับ REST และ GraphQL API ใน Flutter เมื่อเข้าใจแนวคิดเหล่านี้ คุณจะสามารถดึงข้อมูลและจัดการข้อมูลจากแหล่งข้อมูลภายนอกได้อย่างมีประสิทธิภาพ ปรับปรุงฟังก์ชันการทำงานของการทำแอพและประสบการณ์ผู้ใช้ ในขณะที่คุณทำแอพ Flutter ของคุณ

พัฒนาแอพด้วย Flutter

ตอนที่ 6 ทำแอพ Flutter : การจัดการสถานะ (State Management)
ตอนที่ 8 ทำแอพ Flutter : แอนิเมชัน (Animations) และท่าทาง (Gestures)