Simplify HTTP-Client Integration and Loging the Traffic using DioX [Dio Extended] in Flutter

    

   Dio Extended, which I will call DioX from now on, is is a Dart/Flutter package — described as a “thin wrapper” over Dio — designed to simplify HTTP networking for Flutter apps. Rather than dealing directly with raw HTTP calls and manual response handling, DioExtended offers a higher-level API that returns a consistent result object (ApiResult<T>), making code more robust and easier to maintain.

Meet this package on pub.dev

Let me explain more about this package ദ്ദി(˵ •̀ ᴗ - ˵ ) ✧

    One of the common issues with HTTP-client connection security is the token will expire after some time period when we interact with the backend side. I started building this package because of that anxiety. Since I work at a software house that may produce many apps every year, I decided to create this package to reduce boilerplate when starting a new project or product.

🌐 Simplified Networking

    Building and maintaining network layers is often one of the most repetitive and error-prone tasks in Flutter app development. Developers usually deal with raw HTTP responses, try/catch blocks, token handling, and JSON parsing scattered across the codebase.

    DioExtended addresses these problems by offering a simplified, cleaner, and more consistent networking experience on top of the popular Dio HTTP client. Rather than replacing Dio, it acts as a thin wrapper that focuses on reducing boilerplate and improving developer productivity. I call this think with “simplified network”, which means:

  • Minimal boilerplate for API calls
  • Cleaner and unified response handling
  • Built-in support for converting JSON to models
  • Optional automatic token refresh
  • Handy developer tools like shake-to-inspect network logs
Its design makes networking easier while still giving you access to the underlying Dio instance whenever you need more advanced customization.

   DioX unified response handling with ApiResult<T>. Traditional Dio requests require a combination of:

  • try/catch blocks
  • Status code checking
  • Error mapping
  • Manual parsing

    DioExtended simplifies this by returning a single, predictable response wrapper ApiResult<T>

ᯓ➤ Now lets talk about ApiResult<T>

When you using DioX, Every request either returns:

  • ApiResult.success(data)
  • ApiResult.failure(error)

This makes the network layer more uniform, readable, and testable. Just calling result.isSuccess or .isFailure to spliting the result handling.

ᯓ➤ Installation

dependencies:
  dio_extended: ^latest

Create an API instance:
import 'package:dio_extended/dio_extended.dart';

final api = DioExtended(
  baseUrl: 'https://api.example.com',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json',
  },
);

or

class ApiServiceProvider extends DioExtended {
  ApiServiceProvider() : super(baseUrl: 'YOUR-BASE-URL');
  /// Here you can use all function from DioExtend
  /// examples of its use are available ini Request Exampel 
}

ᯓ➤ Making a Simplified GET Request

With DioX, a GET request can be written compactly using callApiRequest:

Future<ApiResult<List<PostModel>>> getPosts() async {
  return await callApiRequest<List<PostModel>>(
    request: () => get('/posts'),
    parseData: (data) => (data as List)
      .map((json) => PostModel.fromJson(json))
      .toList(),
  );
}

What’s simplified?

  • No manual try/catch
  • No parsing scattered around
  • No raw Dio response objects
  • Clean structure with consistent return types
We well got a clear respon in the form of an object model. easy? Because all responses are wrapped in ApiResult<T>, handling data becomes straightforward:

final result = await service.getPosts();
if (result.isSuccess) {
final posts = result.data;
// Update UI or state
} else {
final error = result.error;
// Show error message
}

This pattern ensures you never deal with unpredictable response types. 

Automatic Token Refresh

This is optional thing. DioX supports an elegant solution for handling expired tokens. You can override the method handleTokenExpired:

class AuthService extends DioExtended {
  AuthService() : super(baseUrl: 'https://api.example.com');
  @override
  Future<String?> handleTokenExpired() async {
    final refreshResult = await callApiRequest(
      request: () => post('/auth/refresh'),
      parseData: (json) => json['access_token'],
    );
    if (refreshResult.isSuccess) {
      return refreshResult.data; // New token
    }
    return null; // Token refresh failed
  }
}

With this in place:

  • Any 401 Unauthorized response
  • Will trigger automatic refresh
  • And re-execute the original request

This keeps your authentication logic clean and centralized.

Simplified Debugging: Shake-to-Inspect

    DioX also integrates with ChuckerFlutter, allowing you to open a network inspector simply by shaking the device.

return ShakeForChucker(
child: MyApp(),
useInReleaseMode: false,
shakeCount: 2,
);

This is especially useful for QA and debugging on real devices without logging noise.

 
DioX brings a refreshing level of simplicity to Flutter networking. By abstracting away repetitive tasks and enforcing consistent patterns, it enables developers to focus on application logic rather than network plumbing.

Post a Comment

0 Comments