1. API Error Handling là gì?

Trong quá trình phát triển ứng dụng Flutter, việc giao tiếp với Backend thông qua API là một công việc diễn ra thường xuyên. Khi người dùng đăng nhập, xem sản phẩm, tìm kiếm thông tin, thêm sản phẩm vào giỏ hàng hoặc đặt hàng, ứng dụng thường phải gửi yêu cầu HTTP đến máy chủ và chờ phản hồi.

Tuy nhiên, không phải yêu cầu nào cũng được thực hiện thành công. Trong thực tế, có rất nhiều nguyên nhân khiến việc gọi API gặp sự cố, chẳng hạn như thiết bị mất kết nối Internet, máy chủ không hoạt động, dữ liệu gửi lên không hợp lệ, tài khoản không có quyền truy cập hoặc máy chủ mất quá nhiều thời gian để phản hồi.

Nếu ứng dụng không xử lý những trường hợp này, người dùng có thể gặp tình trạng màn hình tải liên tục, ứng dụng bị lỗi, không có thông báo hoặc không biết thao tác của mình đã được thực hiện thành công hay chưa.

Vì vậy, lập trình viên cần xây dựng cơ chế xử lý lỗi khi giao tiếp với API, được gọi là API Error Handling.

API Error Handling là quá trình phát hiện, phân loại và xử lý những lỗi phát sinh khi ứng dụng gửi yêu cầu đến API, nhận phản hồi từ máy chủ hoặc chuyển đổi dữ liệu nhận được.

Mục đích của API Error Handling không chỉ là ngăn ứng dụng bị crash, mà còn giúp chương trình phản ứng đúng với từng tình huống, thông báo rõ ràng cho người dùng và duy trì trạng thái hoạt động ổn định.

Ví dụ, trong một ứng dụng bán hàng, người dùng nhấn nút “Đặt hàng”. Nếu mạng Internet bị mất ngay lúc đó, ứng dụng không nên chỉ đứng yên hoặc thông báo chung chung rằng có lỗi xảy ra. Thay vào đó, ứng dụng cần phát hiện sự cố kết nối, hiển thị thông báo phù hợp và hướng dẫn người dùng kiểm tra trạng thái đơn hàng trước khi thử lại, tránh tạo đơn trùng lặp.

Như vậy, API Error Handling là một phần quan trọng của quá trình xây dựng ứng dụng có kết nối Backend.

2. Tại sao API Error Handling lại quan trọng?

Khi lập trình trên máy tính cá nhân, lập trình viên thường kiểm thử ứng dụng trong điều kiện mạng ổn định và Backend đang hoạt động bình thường. Điều này có thể tạo cảm giác rằng chỉ cần gửi HTTP Request và nhận JSON Response là đủ.

Tuy nhiên, khi ứng dụng được đưa vào sử dụng thực tế, điều kiện hoạt động có thể thay đổi liên tục.

Người dùng có thể chuyển từ Wi-Fi sang mạng di động, đi vào khu vực mất sóng, sử dụng phiên đăng nhập đã hết hạn hoặc gửi dữ liệu không đúng định dạng. Đồng thời, Backend cũng có thể gặp sự cố cơ sở dữ liệu, quá tải hoặc đang bảo trì.

Nếu không xử lý lỗi, ứng dụng có thể gặp những vấn đề như:

  • Không hiển thị dữ liệu khi API thất bại nhưng cũng không thông báo nguyên nhân.
  • Hiển thị màn hình tải vô thời hạn.
  • Bị crash khi dữ liệu JSON không đúng cấu trúc.
  • Tiếp tục sử dụng token đã hết hạn.
  • Gửi lại yêu cầu không phù hợp và gây ra thao tác trùng lặp.
  • Hiển thị thông báo kỹ thuật khó hiểu đối với người dùng.
  • Không ghi nhận thông tin cần thiết để lập trình viên tìm nguyên nhân lỗi.

Do đó, xử lý lỗi tốt giúp nâng cao trải nghiệm người dùng, tăng độ ổn định của ứng dụng và hỗ trợ quá trình bảo trì hệ thống.

Một ứng dụng được xây dựng tốt không phải là ứng dụng không bao giờ gặp lỗi, mà là ứng dụng có khả năng xử lý những tình huống lỗi có thể dự đoán trước một cách phù hợp.

3. API hoạt động như thế nào và lỗi xuất hiện ở đâu?

Để hiểu API Error Handling, trước tiên cần hiểu luồng giao tiếp giữa Flutter và Backend.

Khi người dùng thực hiện một thao tác cần dữ liệu từ máy chủ, Flutter sẽ tạo HTTP Request. Request được gửi qua mạng đến Backend. Backend tiếp nhận yêu cầu, kiểm tra dữ liệu, thực hiện nghiệp vụ, truy vấn cơ sở dữ liệu nếu cần, sau đó trả về HTTP Response.

Luồng xử lý cơ bản:

Người dùng → Flutter → HTTP Request → Backend → Database → HTTP Response → Flutter → Giao diện

Lỗi có thể xuất hiện ở nhiều giai đoạn khác nhau.

Thứ nhất, lỗi có thể xảy ra trước khi yêu cầu đến được máy chủ. Ví dụ, thiết bị mất mạng hoặc không thể kết nối đến địa chỉ API.

Thứ hai, lỗi có thể xảy ra trong quá trình máy chủ xử lý yêu cầu. Ví dụ, dữ liệu không hợp lệ, tài khoản không đủ quyền hoặc cơ sở dữ liệu gặp sự cố.

Thứ ba, lỗi có thể xuất hiện sau khi máy chủ đã trả về phản hồi. Ví dụ, Backend trả về JSON không đúng cấu trúc mà Flutter đang mong đợi.

Thứ tư, lỗi có thể xảy ra trong quá trình ứng dụng cập nhật trạng thái hoặc giao diện, dù HTTP Request đã hoàn tất.

Vì vậy, API Error Handling cần bao quát cả quá trình gửi yêu cầu, nhận phản hồi, phân tích dữ liệu và cập nhật trạng thái ứng dụng.

4. Phân loại các nhóm lỗi API

Không phải tất cả lỗi API đều giống nhau. Việc phân loại lỗi giúp lập trình viên lựa chọn cách xử lý phù hợp.

4.1. Network Error – Lỗi kết nối mạng

Network Error là lỗi xảy ra khi ứng dụng không thể kết nối hoặc trao đổi dữ liệu với máy chủ qua mạng.

Nguyên nhân có thể bao gồm thiết bị mất Internet, DNS không phân giải được tên miền, kết nối bị ngắt hoặc máy chủ không thể truy cập.

Ví dụ, người dùng mở ứng dụng bán hàng nhưng điện thoại đang ở chế độ máy bay. Khi Flutter gọi API lấy danh sách sản phẩm, yêu cầu có thể thất bại trước khi nhận được bất kỳ HTTP Response nào.

Trong trường hợp này, ứng dụng nên hiển thị thông báo dễ hiểu như “Không thể kết nối đến máy chủ. Vui lòng kiểm tra mạng và thử lại.”

Cần phân biệt rằng thiết bị có kết nối Wi-Fi không đồng nghĩa với việc chắc chắn truy cập được Internet hoặc máy chủ API.

4.2. Timeout Error – Lỗi quá thời gian chờ

Timeout Error xảy ra khi một thao tác không hoàn tất trong khoảng thời gian chờ đã được cấu hình.

Ví dụ, Flutter gửi yêu cầu lấy danh sách sản phẩm nhưng Backend xử lý quá lâu. Nếu ứng dụng thiết lập thời gian chờ là 15 giây và thao tác chưa hoàn thành trong thời gian đó, ứng dụng có thể kết thúc việc chờ và báo lỗi timeout.

Timeout giúp tránh tình trạng ứng dụng phải chờ vô thời hạn.

Tuy nhiên, timeout không có nghĩa là Backend chắc chắn chưa xử lý yêu cầu. Có trường hợp máy chủ đã tạo đơn hàng thành công nhưng phản hồi về điện thoại bị chậm hoặc mất kết nối.

Vì vậy, với các thao tác quan trọng như đặt hàng hoặc thanh toán, ứng dụng cần có cơ chế kiểm tra trạng thái giao dịch trước khi quyết định gửi lại yêu cầu.

4.3. Client Error – Lỗi thuộc nhóm HTTP 4xx

HTTP 4xx cho biết máy chủ không thể hoặc không chấp nhận xử lý yêu cầu theo điều kiện hiện tại, thường do vấn đề liên quan đến request, quyền truy cập hoặc tài nguyên.

Một số mã phổ biến:

400 Bad Request: Máy chủ cho rằng yêu cầu không hợp lệ.

401 Unauthorized: Yêu cầu chưa có thông tin xác thực hợp lệ. Ví dụ, token đăng nhập bị thiếu hoặc không còn hợp lệ.

403 Forbidden: Máy chủ hiểu yêu cầu nhưng từ chối cho phép thực hiện. Ví dụ, tài khoản người dùng thường cố truy cập API quản trị.

404 Not Found: Không tìm thấy tài nguyên được yêu cầu.

409 Conflict: Yêu cầu xung đột với trạng thái hiện tại của tài nguyên, chẳng hạn cập nhật dữ liệu trong một tình huống xung đột.

422 Unprocessable Content: Máy chủ hiểu định dạng yêu cầu nhưng không thể xử lý nội dung theo các quy tắc áp dụng. Mã này thường được dùng cho lỗi validation trong nhiều Backend.

429 Too Many Requests: Ứng dụng hoặc người dùng gửi quá nhiều yêu cầu trong một khoảng thời gian và bị giới hạn.

Điều quan trọng là không nên xử lý tất cả mã 4xx theo cùng một cách. Ví dụ, lỗi 401 có thể yêu cầu đăng nhập lại, trong khi lỗi 422 cần hiển thị những trường dữ liệu chưa hợp lệ để người dùng sửa.

4.4. Server Error – Lỗi thuộc nhóm HTTP 5xx

HTTP 5xx cho biết máy chủ hoặc một thành phần trung gian gặp sự cố trong quá trình xử lý yêu cầu.

Một số mã thường gặp:

500 Internal Server Error: Máy chủ gặp lỗi nội bộ.

502 Bad Gateway: Một máy chủ trung gian nhận phản hồi không hợp lệ từ máy chủ phía sau.

503 Service Unavailable: Dịch vụ hiện không sẵn sàng, có thể do quá tải hoặc bảo trì.

504 Gateway Timeout: Máy chủ trung gian không nhận được phản hồi kịp thời từ máy chủ phía sau.

Với nhóm lỗi này, Flutter thường không thể tự khắc phục nguyên nhân nằm trong Backend. Ứng dụng nên hiển thị thông báo phù hợp, ghi nhận lỗi phục vụ kiểm tra và có thể cho phép người dùng thử lại khi an toàn.

Không nên hiển thị nguyên văn stack trace hoặc thông tin hệ thống nội bộ cho người dùng.

4.5. Parsing Error – Lỗi phân tích dữ liệu

Parsing Error xảy ra khi ứng dụng nhận được dữ liệu nhưng không thể phân tích hoặc chuyển đổi thành cấu trúc mong đợi.

Ví dụ, Flutter mong đợi:

{
  "id": 1,
  "name": "Sữa dinh dưỡng",
  "price": 250000
}

Nhưng Backend lại trả về:

{
  "id": 1,
  "name": null,
  "price": "không xác định"
}

Nếu lớp Dart yêu cầu name là String không nullable và price là số, việc gọi Product.fromJson() có thể phát sinh lỗi.

Trường hợp này không nhất thiết là lỗi HTTP. Máy chủ có thể trả về mã 200 nhưng dữ liệu lại không phù hợp với cấu trúc mà ứng dụng yêu cầu.

Do đó, kiểm tra HTTP Status Code và kiểm tra dữ liệu JSON là hai công việc khác nhau.

4.6. Business Logic Error – Lỗi nghiệp vụ

Lỗi nghiệp vụ xảy ra khi yêu cầu có thể hợp lệ về mặt kỹ thuật nhưng không thể thực hiện do quy tắc hoạt động của hệ thống.

Ví dụ:

  • Người dùng đặt mua 5 sản phẩm nhưng kho chỉ còn 2.
  • Mã giảm giá đã hết hạn.
  • Người dùng yêu cầu hủy một đơn hàng đã giao thành công.
  • Địa chỉ giao hàng không được phép thay đổi khi đơn đã chuyển sang trạng thái giao hàng.

Backend cần kiểm tra những quy tắc này và trả về phản hồi phù hợp. Tùy trường hợp, có thể sử dụng những mã HTTP như 409 hoặc 422 cùng mã lỗi nghiệp vụ cụ thể trong response body.

Ứng dụng Flutter nên đọc mã lỗi nghiệp vụ để hiển thị thông báo chính xác, thay vì chỉ thông báo “Có lỗi xảy ra”.

5. HTTP Status Code có phải là Exception không?

Đây là điểm rất dễ nhầm lẫn khi mới học API Error Handling.

HTTP Status Code là mã trạng thái được máy chủ trả về trong HTTP Response. Trong khi đó, Exception là cơ chế mà ngôn ngữ lập trình sử dụng để biểu diễn một tình huống bất thường trong quá trình thực thi.

Hai khái niệm này có liên quan nhưng không giống nhau.

Ví dụ, khi dùng package http trong Dart, máy chủ trả về HTTP 404 không nhất thiết khiến hàm http.get() tự động ném Exception. Thông thường, lập trình viên vẫn nhận được đối tượng Response và cần tự kiểm tra response.statusCode.

Ngược lại, nếu thiết bị không thể kết nối đến máy chủ, quá trình gửi request có thể phát sinh Exception mà không có HTTP Response nào được nhận.

Vì vậy, cần phân biệt:

Có HTTP Response nhưng mã trạng thái báo lỗi: Kiểm tra statusCode và xử lý nội dung phản hồi.

Không nhận được HTTP Response do sự cố kết nối hoặc thời gian chờ: Bắt Exception phù hợp.

Nhận được HTTP Response thành công nhưng dữ liệu sai cấu trúc: Xử lý lỗi parsing hoặc mapping dữ liệu.

Việc hiểu đúng ba tình huống này giúp lập trình viên xây dựng cơ chế xử lý lỗi chính xác hơn.

6. Xử lý lỗi bằng try-catch trong Dart

Trong Dart, try-catch được sử dụng để xử lý những Exception phát sinh khi chương trình thực hiện một thao tác.

Cấu trúc cơ bản:

try {
  // Thực hiện công việc có thể phát sinh lỗi
} catch (e) {
  // Xử lý lỗi
}

Ví dụ:

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

Future<void> fetchProducts() async {
  try {
    final response = await http.get(
      Uri.parse('https://example.com/api/products'),
    );

    if (response.statusCode == 200) {
      final data = jsonDecode(response.body);
      print(data);
    } else {
      print('API trả về lỗi: ${response.statusCode}');
    }
  } catch (e) {
    print('Có lỗi xảy ra: $e');
  }
}

Trong đoạn code này, khối try chứa thao tác gửi HTTP Request và phân tích JSON.

Nếu có Exception phát sinh, chương trình chuyển sang khối catch để xử lý.

Tuy nhiên, đoạn code trên chỉ là ví dụ cơ bản. Trong ứng dụng thực tế, không nên dùng một catch chung cho mọi lỗi rồi coi tất cả đều là lỗi kết nối. Exception có thể xuất phát từ nhiều nguyên nhân khác nhau, chẳng hạn lỗi socket, timeout, JSON sai cú pháp hoặc ép kiểu dữ liệu.

Vì vậy, ứng dụng nên phân loại lỗi thành những nhóm cụ thể để xử lý đúng hơn.

7. Xây dựng lớp lỗi riêng cho ứng dụng

Trong dự án Flutter lớn, nếu mỗi màn hình đều tự kiểm tra mã trạng thái HTTP và tự viết thông báo lỗi, code sẽ dễ bị trùng lặp và thiếu nhất quán.

Một giải pháp là xây dựng lớp lỗi riêng, ví dụ ApiException.

class ApiException implements Exception {
  final int? statusCode;
  final String message;

  ApiException({
    this.statusCode,
    required this.message,
  });

  @override
  String toString() => message;
}

Lớp này giúp ứng dụng biểu diễn lỗi API dưới một cấu trúc thống nhất.

Ví dụ:

if (response.statusCode == 401) {
  throw ApiException(
    statusCode: 401,
    message: 'Phiên đăng nhập không hợp lệ',
  );
}

if (response.statusCode == 404) {
  throw ApiException(
    statusCode: 404,
    message: 'Không tìm thấy dữ liệu',
  );
}

Trong ứng dụng thực tế, có thể mở rộng lớp lỗi để lưu thêm mã lỗi nghiệp vụ, nguyên nhân kỹ thuật, thông tin validation hoặc dữ liệu phục vụ ghi log.

Tuy nhiên, cần phân biệt thông báo kỹ thuật dành cho lập trình viên và thông báo thân thiện dành cho người dùng. Không nên lấy mọi thông báo từ máy chủ rồi hiển thị nguyên văn lên giao diện.

8. Xử lý API Error Handling với Dio

Dio là một HTTP Client dành cho Dart, cung cấp nhiều chức năng hỗ trợ gửi request, nhận response và xử lý lỗi.

Một điểm hữu ích của Dio là cơ chế DioException, giúp lập trình viên phân biệt những nhóm lỗi thường gặp.

Ví dụ:

import 'package:dio/dio.dart';

final dio = Dio(
  BaseOptions(
    baseUrl: 'https://example.com/api',
    connectTimeout: const Duration(seconds: 10),
    receiveTimeout: const Duration(seconds: 15),
  ),
);

Future<void> fetchProducts() async {
  try {
    final response = await dio.get('/products');

    print(response.data);
  } on DioException catch (e) {
    switch (e.type) {
      case DioExceptionType.connectionTimeout:
        print('Kết nối đến máy chủ quá thời gian');
        break;

      case DioExceptionType.receiveTimeout:
        print('Nhận phản hồi quá thời gian');
        break;

      case DioExceptionType.connectionError:
        print('Không thể kết nối đến máy chủ');
        break;

      case DioExceptionType.badResponse:
        print(
          'Máy chủ trả về mã: ${e.response?.statusCode}',
        );
        break;

      case DioExceptionType.cancel:
        print('Yêu cầu đã bị hủy');
        break;

      default:
        print('Đã xảy ra lỗi: ${e.message}');
    }
  }
}

Đoạn code này phân loại một số lỗi thường gặp theo DioExceptionType.

connectionTimeout cho biết quá thời gian thiết lập kết nối. receiveTimeout liên quan đến thời gian chờ nhận dữ liệu. connectionError thể hiện sự cố kết nối. badResponse thường được sử dụng khi mã HTTP không thỏa mãn quy tắc validateStatus của Dio.

Cần lưu ý rằng cách Dio phân loại HTTP Response phụ thuộc vào cấu hình validateStatus. Nếu cấu hình cho phép một mã trạng thái được xem là phản hồi hợp lệ, mã đó có thể không tạo ra DioExceptionType.badResponse.

Ngoài ra, các loại lỗi khác như sendTimeout, badCertificate hoặc unknown cũng cần được xem xét trong ứng dụng thực tế.

9. Interceptor trong xử lý lỗi API

Interceptor là một cơ chế cho phép can thiệp vào quá trình xử lý HTTP Request, HTTP Response và lỗi tại một vị trí tập trung.

Thay vì mỗi API tự thêm token hoặc tự xử lý một số lỗi lặp lại, lập trình viên có thể cấu hình Interceptor để thực hiện những công việc chung.

Ví dụ:

dio.interceptors.add(
  InterceptorsWrapper(
    onRequest: (options, handler) {
      print('Đang gọi API: ${options.path}');
      handler.next(options);
    },
    onResponse: (response, handler) {
      print('API thành công: ${response.statusCode}');
      handler.next(response);
    },
    onError: (error, handler) {
      print('API thất bại: ${error.message}');
      handler.next(error);
    },
  ),
);

Ví dụ trên chỉ minh họa cơ chế Interceptor.

Trong dự án thật, Interceptor có thể được sử dụng để thêm Authorization Header, ghi log có kiểm soát, xử lý một số lỗi xác thực hoặc chuẩn hóa phản hồi.

Tuy nhiên, không nên ghi toàn bộ request và response một cách tùy tiện, vì chúng có thể chứa mật khẩu, token hoặc thông tin cá nhân.

Việc xử lý tự động làm mới token cũng cần được thiết kế cẩn thận để tránh nhiều request đồng thời cùng thực hiện refresh hoặc tạo vòng lặp khi refresh thất bại.

10. Retry – Có nên tự động gửi lại API khi gặp lỗi?

Retry là cơ chế thử thực hiện lại một yêu cầu sau khi yêu cầu trước đó thất bại.

Ví dụ, ứng dụng gọi API lấy danh sách sản phẩm nhưng mạng bị gián đoạn trong thời gian ngắn. Khi đó, ứng dụng có thể thử gửi lại request.

Tuy nhiên, không phải yêu cầu nào cũng nên tự động retry.

Với những yêu cầu chỉ đọc dữ liệu như GET /products, việc retry thường ít rủi ro hơn nếu API được thiết kế đúng.

Ngược lại, với yêu cầu tạo đơn hàng hoặc thanh toán, tự động retry có thể gây ra thao tác trùng lặp nếu máy chủ đã xử lý thành công nhưng phản hồi không đến được ứng dụng.

Một hệ thống có thể sử dụng idempotency key để nhận diện những lần gửi lại cùng một thao tác, nhưng cơ chế này phải được Backend hỗ trợ.

Ngoài ra, khi retry nên giới hạn số lần thử và sử dụng khoảng chờ tăng dần, thường gọi là exponential backoff. Nếu máy chủ trả về HTTP 429 kèm Retry-After, ứng dụng nên cân nhắc hướng dẫn đó thay vì liên tục gửi lại yêu cầu.

Như vậy, retry không đơn giản là gặp lỗi thì gọi lại API. Cần xem xét loại request, nguyên nhân lỗi và khả năng tạo tác dụng phụ.

11. Hiển thị lỗi trên giao diện Flutter

Một phần quan trọng của API Error Handling là cách ứng dụng phản hồi với người dùng.

Thông thường, một màn hình lấy dữ liệu từ API có thể có các trạng thái:

  • Loading: Đang tải dữ liệu.
  • Success: Tải dữ liệu thành công.
  • Empty: Tải thành công nhưng không có dữ liệu.
  • Error: Không thể tải dữ liệu do lỗi.
  • Unauthenticated: Cần đăng nhập hoặc xác thực lại.

Ví dụ, khi mở trang sản phẩm, ứng dụng có thể hiển thị biểu tượng tải trong lúc gọi API. Nếu API thành công nhưng danh sách rỗng, giao diện hiển thị thông báo chưa có sản phẩm. Nếu mất mạng, giao diện hiển thị thông báo kết nối thất bại và nút thử lại.

Không nên nhầm lẫn giữa trạng thái danh sách rỗng và trạng thái lỗi. Hai tình huống này có ý nghĩa khác nhau.

Ngoài ra, khi thực hiện thao tác như đặt hàng, ứng dụng nên ngăn việc nhấn nút nhiều lần trong lúc đang xử lý, nhưng vẫn cần cơ chế bảo vệ ở Backend để tránh tạo dữ liệu trùng lặp.

12. Logging và Debugging khi API gặp lỗi

Logging là quá trình ghi lại thông tin về hoạt động của chương trình nhằm phục vụ kiểm tra và phân tích.

Khi API thất bại, lập trình viên có thể cần biết endpoint nào được gọi, mã trạng thái HTTP là gì, lỗi xuất hiện vào thời điểm nào và request có mã nhận diện nào.

Thông tin này giúp tìm nguyên nhân nhanh hơn so với việc chỉ thấy thông báo “Có lỗi xảy ra”.

Trong quá trình phát triển, có thể sử dụng Flutter DevTools, Dio Interceptor hoặc những công cụ theo dõi mạng để kiểm tra request và response.

Tuy nhiên, việc ghi log phải có giới hạn. Không nên ghi mật khẩu, access token, thông tin thanh toán hoặc dữ liệu cá nhân không cần thiết.

Đối với môi trường production, hệ thống có thể sử dụng dịch vụ theo dõi lỗi như Firebase Crashlytics hoặc những nền tảng giám sát phù hợp để ghi nhận lỗi một cách có kiểm soát.

13. Những sai lầm thường gặp khi xử lý lỗi API

Sai lầm đầu tiên là chỉ kiểm tra HTTP 200 và cho rằng tất cả trường hợp khác đều giống nhau. Thực tế, lỗi xác thực, lỗi dữ liệu và lỗi máy chủ cần cách xử lý khác nhau.

Sai lầm thứ hai là sử dụng một khối catch chung rồi hiển thị “Không có Internet” cho mọi Exception. Điều này có thể khiến người dùng hiểu sai nguyên nhân.

Sai lầm thứ ba là tự động retry mọi request, kể cả yêu cầu tạo đơn hàng hoặc thanh toán, dẫn đến nguy cơ thực hiện thao tác nhiều lần.

Sai lầm thứ tư là hiển thị nguyên văn lỗi kỹ thuật của Backend cho người dùng. Những thông báo này có thể khó hiểu hoặc làm lộ thông tin nội bộ.

Sai lầm thứ năm là không xử lý trạng thái Loading và Error trên giao diện, khiến người dùng không biết ứng dụng đang làm gì.

Sai lầm cuối cùng là chỉ xử lý lỗi ở Flutter mà bỏ qua việc kiểm tra dữ liệu tại Backend. Frontend có thể hỗ trợ trải nghiệm người dùng, nhưng Backend vẫn phải tự kiểm tra quyền truy cập, dữ liệu đầu vào và quy tắc nghiệp vụ.

14. Kết luận

API Error Handling là quá trình phát hiện, phân loại và xử lý những lỗi phát sinh khi ứng dụng Flutter giao tiếp với Backend.

Lỗi có thể xuất hiện trong quá trình kết nối mạng, chờ phản hồi, xử lý HTTP Status Code, phân tích JSON hoặc thực hiện quy tắc nghiệp vụ. Vì vậy, lập trình viên không nên chỉ sử dụng try-catch một cách chung chung mà cần hiểu từng loại lỗi để đưa ra cách xử lý phù hợp.

Trong Flutter, có thể sử dụng package http hoặc Dio để gửi yêu cầu và xử lý phản hồi. Với những dự án lớn, việc xây dựng lớp lỗi riêng, sử dụng Interceptor, quản lý trạng thái giao diện và ghi log có kiểm soát sẽ giúp code dễ bảo trì hơn.

Điều quan trọng nhất là xử lý lỗi không chỉ nhằm tránh crash mà còn giúp ứng dụng hoạt động ổn định, bảo vệ dữ liệu và mang lại trải nghiệm rõ ràng cho người dùng ngay cả khi hệ thống gặp sự cố.

15. Tài liệu tham khảo

Bài viết khác

Tìm hiểu Flutter Flavors & Multiple Environments là gì?

1. Flutter Flavors & Multiple Environments là gì? Trong quá trình phát triển một ứng dụng Flutter, lập trình viên thường phải xây dựng, kiểm thử và phát hành ứng dụng qua nhiều giai đoạn khác nhau. Ví dụ, khi mới phát triển ứng dụng, lập trình viên cần kết nối với Backend đang chạy […]

 TÌM HIỂU CHI TIẾT VỀ FIREBASE ANALYTICS TRONG FLUTTER

 1. Firebase Analytics là gì? Trong quá trình phát triển ứng dụng, việc xây dựng giao diện đẹp và các chức năng hoạt động đúng là rất quan trọng. Tuy nhiên, khi ứng dụng được đưa vào sử dụng thực tế, lập trình viên và doanh nghiệp còn cần biết người dùng đang sử dụng […]

TÌM HIỂU CHI TIẾT VỀ FIREBASE CLOUD MESSAGING (FCM) TRONG FLUTTER

1. Firebase Cloud Messaging (FCM) là gì? Trong quá trình phát triển ứng dụng di động, ngoài việc hiển thị thông tin khi người dùng đang sử dụng ứng dụng, lập trình viên còn cần có cơ chế gửi thông báo đến thiết bị khi có sự kiện mới xảy ra. Ví dụ, trong một […]

Unit & Integration Testing

1. Testing là gì và tại sao Backend cần Testing? Software Testing là quá trình kiểm tra phần mềm để xác minh rằng hệ thống hoạt động đúng theo yêu cầu, phát hiện lỗi và hạn chế những thay đổi làm hỏng chức năng đã tồn tại. Trong Backend, một chức năng thường không chỉ […]

Gin-Gonic

1. Gin-Gonic là gì? Gin-Gonic là một web framework được viết bằng ngôn ngữ lập trình Go (Golang), hỗ trợ xây dựng các ứng dụng web và REST API một cách nhanh chóng, thuận tiện. Thay vì phải tự viết toàn bộ chức năng xử lý HTTP, lập trình viên có thể sử dụng những […]

TÌM HIỂU CHI TIẾT VỀ JSON SERIALIZATION / DESERIALIZATION TRONG FLUTTE

1. JSON Serialization / Deserialization là gì? Trong quá trình phát triển ứng dụng, đặc biệt là ứng dụng Flutter có kết nối với Backend, việc trao đổi dữ liệu giữa các thành phần là một công việc rất quan trọng. Ví dụ, khi người dùng mở ứng dụng bán sữa, ứng dụng cần lấy […]

Leave a Reply

Your email address will not be published. Required fields are marked *