+33

Gọi API thật trong Flutter & hiển thị dữ liệu với FutureBuilder

Ở bài trước, chúng ta đã học cách tạo model và chuyển đổi dữ liệu từ JSON. Hôm nay, mình quyết định gọi API thật để lấy dữ liệu về và hiển thị nó lên UI

Mục tiêu bài học

  • Cài package http để gọi API
  • Gọi API REST trả về danh sách JSON
  • Parse dữ liệu về model
  • Hiển thị dữ liệu bằng FutureBuilder

1. Cài đặt package http

Để có thể gọi API, chúng ta cần thêm package http vào dự án. Mở file pubspec.yaml và thêm dòng sau vào phần dependencies:

dependencies:
  http: ^1.4.0

Sau đó, chạy lệnh sau trong terminal để tải package:

flutter pub get

2. Tạo model đơn giản

Hôm nay chúng ta sẽ sử dụng API example sau nhé https://jsonplaceholder.typicode.com/users. Trong API này dữ liệu JSON có dạng như sau:

{
    "id": 1,
    "name": "Leanne Graham",
    "username": "Bret",
    "email": "Sincere@april.biz",
    "address": {
      "street": "Kulas Light",
      "suite": "Apt. 556",
      "city": "Gwenborough",
      "zipcode": "92998-3874",
      "geo": {
        "lat": "-37.3159",
        "lng": "81.1496"
      }
    },
    "phone": "1-770-736-8031 x56442",
    "website": "hildegard.org",
    "company": {
      "name": "Romaguera-Crona",
      "catchPhrase": "Multi-layered client-server neural-net",
      "bs": "harness real-time e-markets"
    }
  }

Tuy nhiên hôm nay mình sẽ chỉ sử dụng các thuộc tính cơ bản như id, name, email thôi nhé. Bây giờ chúng ta sẽ bắt đầu xây dựng Model User như sau:

class User {
  final int id;
  final String name;
  final String email;

  User({required this.id, required this.name, required this.email});

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      id: json['id'],
      name: json['name'],
      email: json['email'],
    );
  }
}

3. Gọi API với http.get

Tiếp theo, chúng ta sẽ tạo một hàm bất đồng bộ để thực hiện yêu cầu HTTP và lấy dữ liệu người dùng. Hãy đặt hàm này trong một file riêng hoặc cùng với model User nếu bạn muốn.

import 'package:http/http.dart' as http;
import 'dart:convert';
// Đảm bảo bạn đã định nghĩa class User ở đây hoặc import từ file khác
// import 'user.dart';

Future<List<User>> fetchUsers() async {
  final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/users'));

  if (response.statusCode == 200) {
    // Nếu server trả về mã trạng thái 200 OK, parse JSON
    List jsonData = json.decode(response.body);
    // Chuyển đổi List JSON thành List các đối tượng User
    return jsonData.map((e) => User.fromJson(e)).toList();
  } else {
    // Nếu server không trả về mã 200 OK, ném ra một ngoại lệ
    throw Exception('Failed to load users');
  }
}

4. Hiển thị với FutureBuilder

Bây giờ chúng ta sẽ dùng FutureBuilder để gọi fetchUsers() và hiển thị kết quả:

import 'package:flutter/material.dart';
// Đảm bảo import file chứa hàm fetchUsers() và class User
// import 'user_service.dart'; 
// import 'user.dart'; 

class UserListScreen extends StatelessWidget {
  const UserListScreen({super.key});

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Danh sách người dùng')),
      body: FutureBuilder<List<User>>(
        future: fetchUsers(), // Hàm fetchUsers() sẽ được gọi
        builder: (context, snapshot) {
          // Trạng thái chờ dữ liệu
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Center(child: CircularProgressIndicator());
          } 
          // Trạng thái có lỗi
          else if (snapshot.hasError) {
            return Center(child: Text('Lỗi: ${snapshot.error}'));
          } 
          // Trạng thái không có dữ liệu hoặc dữ liệu rỗng
          else if (!snapshot.hasData || snapshot.data!.isEmpty) {
            return const Center(child: Text('Không có dữ liệu'));
          }

          // Trạng thái có dữ liệu, hiển thị danh sách
          final users = snapshot.data!;

          return ListView.builder(
            itemCount: users.length,
            itemBuilder: (context, index) {
              final user = users[index];
              return ListTile(
                leading: CircleAvatar(child: Text(user.id.toString())),
                title: Text(user.name),
                subtitle: Text(user.email),
              );
            },
          );
        },
      ),
    );
  }
}

Và đây là kết quả của chúng ta 🤣🤣🤣 image.png

Kết luận

Qua bài học này, bạn đã nắm được cách thực hiện một yêu cầu HTTP để lấy dữ liệu từ API, parse dữ liệu JSON thành các đối tượng Dart, và hiển thị chúng một cách hiệu quả trên giao diện người dùng bằng FutureBuilder. Đây là một kỹ năng nền tảng quan trọng cho mọi ứng dụng Flutter cần tương tác với dữ liệu từ xa.

Hẹn gặp lại các bạn ở bài viết tiếp theo nhé. Nếu bài viết có vấn đề gì hoặc các bạn có góp ý gì thì hãy cmt ở dưới giúp mình nhé.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí