Giới thiệu REST API trong FLUTTER

Hướng dẫn căn bản: Cách tích hợp REST API  trong Flutter

Trong quá trình học và phát triển ứng dụng di động với Flutter, bạn sẽ nhận ra rằng một ứng dụng không thể chỉ hoạt động với dữ liệu tĩnh trên máy. Để ứng dụng "sống" và liên tục cập nhật thông tin (như đọc báo, xem danh sách sản phẩm, hiển thị thời tiết), bạn cần phải kết nối nó với máy chủ (server). Và cầu nối phổ biến nhất để làm việc này chính là REST API.

Hướng dẫn căn bản: Cách tích hợp REST API  trong Flutter


Bài viết này sẽ giải thích cho bạn REST API là gì theo ngôn ngữ đơn giản nhất, cũng như hướng dẫn chi tiết từng bước cách gọi một API trong Flutter để hiển thị dữ liệu lên màn hình. Hãy cùng bắt đầu nhé!



1. REST API là gì? Hiểu sao cho đơn giản?

Hãy tưởng tượng bạn đang vào một nhà hàng. Bạn (Ứng dụng Flutter - Client) muốn gọi món ăn. Nhà bếp (Máy chủ - Server) là nơi có nguyên liệu và chế biến món ăn. Tuy nhiên, bạn không thể tự chạy vào bếp lấy đồ ăn được. Bạn cần một người Bồi bàn (API) để ghi lại yêu cầu của bạn, mang vào bếp, và sau đó bưng món ăn từ bếp ra bàn cho bạn.

REST API (Representational State Transfer Application Programming Interface) chính là "người bồi bàn" đó trên môi trường internet. Nó tuân theo một bộ quy tắc nhất định để Client và Server có thể nói chuyện được với nhau.

Trong REST API, chúng ta có 4 hành động (phương thức) cơ bản tương ứng với chuẩn CRUD (Create, Read, Update, Delete):

  • GET (Read): Lấy dữ liệu từ server về (Ví dụ: Lấy danh sách sản phẩm).
  • POST (Create): Gửi dữ liệu mới lên server (Ví dụ: Tạo tài khoản mới, Gửi bình luận).
  • PUT / PATCH (Update): Cập nhật dữ liệu đã có trên server.
  • DELETE (Delete): Xóa dữ liệu trên server.

Dữ liệu trao đổi qua lại thường được định dạng dưới dạng JSON (JavaScript Object Notation) - một định dạng văn bản rất dễ đọc cho cả người và máy.

2. Tại sao ứng dụng Flutter của bạn lại cần API?

Sử dụng API mang lại những lợi ích khổng lồ cho ứng dụng di động:

  • Dữ liệu luôn mới: Bạn không cần bắt người dùng cập nhật ứng dụng trên App Store chỉ để đổi một dòng chữ hay thêm một sản phẩm. Mọi thứ được tải từ server xuống theo thời gian thực.
  • Tiết kiệm dung lượng: Ứng dụng sẽ rất nhẹ vì dữ liệu (hình ảnh, văn bản, video) nằm ở server, ứng dụng chỉ tải về những thứ cần thiết khi người dùng lướt tới.
  • Đồng bộ đa nền tảng: Bạn có thể dùng chung một REST API cho cả ứng dụng Flutter (iOS/Android), ứng dụng Web và ứng dụng Desktop. Đảm bảo mọi nền tảng đều thấy cùng một dữ liệu.

3. Ví dụ minh họa: Gọi API hiển thị danh sách bài viết

Trong ví dụ này, chúng ta sẽ sử dụng một Fake API miễn phí dành cho lập trình viên là JSONPlaceholder để lấy về một danh sách các bài viết (Posts) bằng phương thức GET.

Đường dẫn API: https://jsonplaceholder.typicode.com/posts

Bước 1: Cài đặt gói thư viện HTTP

Flutter mặc định không có sẵn công cụ tối ưu để gọi API, nên chúng ta sẽ sử dụng một thư viện (package) rất phổ biến của Google là http.

Mở file pubspec.yaml trong project của bạn và thêm dòng sau vào dưới mục dependencies:

dependencies:
  flutter:
    sdk: flutter
  http: ^1.1.0 # Thêm thư viện http tại đây

Sau đó chạy lệnh flutter pub get trong terminal để tải thư viện về.

Bước 2: Tạo Lớp Dữ Liệu (Model)

Khi gọi API, dữ liệu trả về là một chuỗi JSON (text). Để Flutter có thể hiểu và dễ dàng lấy ra các thông tin (như tiêu đề, nội dung), chúng ta cần chuyển đổi chuỗi JSON đó thành một đối tượng Dart. Ở đây ta tạo một class Post.

class Post {
  final int id;
  final String title;
  final String body;

  Post({required this.id, required this.title, required this.body});

  // Hàm chuyển đổi từ JSON (Map) sang Object Dart
  factory Post.fromJson(Map<String, dynamic> json) {
    return Post(
      id: json['id'],
      title: json['title'],
      body: json['body'],
    );
  }
}

Bước 3: Viết hàm bất đồng bộ để gọi API (Fetch Data)

Việc kết nối mạng sẽ tốn thời gian (có thể nhanh hoặc chậm tùy mạng). Do đó, chúng ta phải sử dụng hàm bất đồng bộ (Future, async, await) để ứng dụng không bị đơ trong lúc chờ đợi server phản hồi.

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

Future<List<Post>> fetchPosts() async {
  // Gửi request GET tới server
  final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts'));

  // Kiểm tra mã trạng thái (StatusCode 200 nghĩa là thành công)
  if (response.statusCode == 200) {
    // Ép kiểu dữ liệu chuỗi trả về sang dạng List
    List jsonResponse = jsonDecode(response.body);
    // Chuyển đổi List JSON sang List<Post>
    return jsonResponse.map((data) => Post.fromJson(data)).toList();
  } else {
    // Nếu lỗi, ném ra một ngoại lệ
    throw Exception('Không thể tải danh sách bài viết');
  }
}

Bước 4: Hiển thị dữ liệu lên giao diện với FutureBuilder

Để vẽ giao diện dựa trên dữ liệu đang tải từ mạng, Flutter cung cấp một Widget tuyệt vời có tên là FutureBuilder. Nó sẽ tự động cập nhật UI tùy theo trạng thái: Đang tải, Tải lỗi, hoặc Tải thành công.

import 'package:flutter/material.dart';

class PostListScreen extends StatefulWidget {
  @override
  _PostListScreenState createState() => _PostListScreenState();
}

class _PostListScreenState extends State<PostListScreen> {
  late Future<List<Post>> futurePosts;

  @override
  void initState() {
    super.initState();
    // Gọi hàm fetch data ngay khi màn hình khởi tạo
    futurePosts = fetchPosts();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Danh Sách Bài Viết API')),
      body: FutureBuilder<List<Post>>(
        future: futurePosts,
        builder: (context, snapshot) {
          // Trạng thái 1: Đang tải dữ liệu
          if (snapshot.connectionState == ConnectionState.waiting) {
            return Center(child: CircularProgressIndicator());
          } 
          // Trạng thái 2: Có lỗi xảy ra
          else if (snapshot.hasError) {
            return Center(child: Text('Lỗi: ${snapshot.error}'));
          } 
          // Trạng thái 3: Tải thành công và có dữ liệu
          else if (snapshot.hasData) {
            List<Post> posts = snapshot.data!;
            return ListView.builder(
              itemCount: posts.length,
              itemBuilder: (context, index) {
                return Card(
                  margin: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
                  child: ListTile(
                    leading: CircleAvatar(child: Text(posts[index].id.toString())),
                    title: Text(posts[index].title, style: TextStyle(fontWeight: FontWeight.bold)),
                    subtitle: Text(posts[index].body, maxLines: 2, overflow: TextOverflow.ellipsis),
                  ),
                );
              },
            );
          }
          // Trạng thái mặc định
          return Center(child: Text('Không có dữ liệu'));
        },
      ),
    );
  }
}

4. Những lưu ý quan trọng khi làm việc với API

Để ứng dụng của bạn trở nên chuyên nghiệp và ít gặp lỗi (bug) khi người dùng sử dụng, bạn cần chú ý những điểm sau khi làm việc với REST API:

  • Xử lý lỗi (Error Handling): Không phải lúc nào server cũng trả về kết quả thành công (Mã 200). Đôi khi mất mạng, đôi khi link API bị sai (Mã 404), hoặc lỗi từ server (Mã 500). Bạn phải luôn có khối lệnh try-catch hoặc xử lý statusCode cẩn thận để ứng dụng không bị văng (crash) bất ngờ.
  • Parsing JSON cẩn thận: Kiểu dữ liệu từ API trả về có thể thay đổi (ví dụ API hứa trả về một chuỗi String nhưng lại trả về null). Bạn nên kiểm tra null an toàn (Null Safety) khi chuyển đổi JSON. Các lập trình viên thường dùng thư viện như json_serializable hoặc freezed để tự động hóa và làm an toàn quá trình này thay vì tự viết tay.
  • Quản lý trạng thái (State Management): Trong các ứng dụng thực tế lớn, thay vì dùng setState hay FutureBuilder ở mọi nơi, người ta sẽ kết hợp gọi API với các công cụ quản lý trạng thái như Provider, Riverpod, BLoC hoặc GetX để cấu trúc code gọn gàng, tách biệt phần Giao diện (UI) và phần Xử lý dữ liệu (Logic) ra khỏi nhau.

5. Lời kết

Kết nối REST API trong Flutter ban đầu có thể trông hơi phức tạp vì có liên quan đến các khái niệm bất đồng bộ (async/await) và chuyển đổi JSON. Tuy nhiên, khi bạn đã làm quen với mô hình cơ bản (Tạo Model -> Viết hàm gọi HTTP -> Dùng FutureBuilder hiển thị), bạn sẽ thấy nó cực kỳ logic và mạnh mẽ.

Hi vọng bài viết này đã giúp bạn hiểu rõ bản chất của API và tự tin triển khai thành công tính năng này vào ứng dụng Flutter của mình. Hãy thử thay đổi đường dẫn API trong ví dụ trên bằng một API thời tiết hay giá coin để thấy sự thú vị nhé. Chúc các bạn code vui vẻ!

Categories

AI (13) AI programming (1) ASP (1) Android (32) App Honeygain (4) Assembly (17) Biểu diễn thuật toán (1) Bubble-Sort (1) Bài giảng (2) Bài giảng lập trình C và Cpp (21) Bài viết hay (108) Bản đồ tư duy (1) C Plus Plus (103) C/C++ (16) CDSL phân tán (1) CSS (2) Cơ sở dữ liệu (11) Danh ngôn lập trình (1) Datamining (4) Genetic Algorithm (1) Giáo trình (2) Giải thuật tiến hóa - thuật toán di truyền (2) Google App Engine (2) Góc học tập (34) HTML (1) Hướng dẫn kiếm tiền online tại nhà (6) Hướng dẫn sử dụng Emu8086 (1) Học lập trình (131) Học lập trình C và CPP qua ví dụ (17) Java (54) Java Căn bản (6) JavaScript (5) Kỹ năng đọc hiệu quả (1) Kỹ thuật lập trình (16) Kỹ thuật đồ họa máy tính (10) Lý thuyết Cơ sở dữ liệu (2) Lý thuyết đồ thị (11) Lập trình Cơ sở dữ liệu (2) Lập trình Python (2) Lập trình căn bản (8) Lập trình hướng đối tượng với Java (7) Lập trình mobile (8) Lập trình mạng (6) Lập trình nhúng (1) Lập trình trí tuệ nhân tạo (2) ML (1) MMO (6) MS Access (1) Machine learning (2) Mạng máy tính (1) Mẹo tìm kiếm trên Google (1) Nghiên cứu khoa học (3) Ngôn ngữ lập trình (2) Những cuốn sách hay mà bạn nên đọc khi còn trẻ (1) Pascal (3) Phương pháp tính toán tối ưu (2) Phương pháp tối ưu (2) Quản lý dự án CNTT (1) SEO (1) SQL (5) Swift (9) Sách hay (4) Thiết kế Web (2) Thuật toán (51) Thuật toán Sắp Xếp -Sort (9) Thuật toán Tìm kiếm - Search (5) Thuật toán di truyền (4) Thực hành Android (2) Tin học văn phòng (5) Tiện ích máy tính (3) Toán rời rạc (13) Treo máy kiếm tiền (3) Trí tuệ nhân tạo (18) Tài liệu tham khảo (4) Tìm hiểu Blockchain (2) Tự học Android (3) Tự học Android qua ví dụ (1) Tự học JavaScript (1) Tự học lập trình (8) Tự học lập trình Android (17) Tự học lập trình C và CPP (14) Tự học lập trình java qua các ví dụ (8) XML (1) blockchain (2) bài giảng quản lý dự án CNTT (1) bài tập java (3) bài tập lập trình (4) cấu trúc dữ liệu giải thuật (15) hướng dẫn viết báo (1) học lập trình Java (11) học máy (5) hợp ngữ (8) lập trình viên (3) phưng pháp đơn hình (2) thuật toán AI (2) tài liệu CNTT miễn phí (3) tính toán tối ưu (1) tự học lập trình iOS (8) tự học lập trình python (1) ví dụ Assembly (1) Đại số gia tử và ứng dụng (1) Đồ họa (4)