dio_flow 1.3.3 copy "dio_flow: ^1.3.3" to clipboard
dio_flow: ^1.3.3 copied to clipboard

Flexible HTTP client for Flutter, built on Dio with mock support, GraphQL, file handling, caching, and token management.

๐ŸŒŠ Dio Flow #

pub package License: MIT Flutter Platform

A powerful, production-ready Flutter package that supercharges Dio HTTP client

Built for modern Flutter applications that demand robust, scalable API integration

๐Ÿ“– Documentation โ€ข ๐Ÿš€ Quick Start โ€ข ๐Ÿ’ก Examples โ€ข ๐Ÿ› Issues


๐ŸŽฏ Why Dio Flow? #

Dio Flow transforms your API integration experience by providing enterprise-grade features out of the box:

  • ๐Ÿ”ฅ Zero Configuration: Get started in minutes with sensible defaults
  • ๐Ÿ›ก๏ธ Production Ready: Battle-tested with comprehensive error handling
  • ๐Ÿš€ Performance First: Built-in caching, retry logic, and request optimization
  • ๐ŸŒ Universal: Works seamlessly across all Flutter platforms
  • ๐Ÿงช Developer Friendly: Extensive mocking support for testing
  • ๐Ÿ“Š Observable: Built-in metrics and detailed logging

๐Ÿ“‹ Table of Contents #

โœจ Features #

๐Ÿš€ Core ๐Ÿ”’ Security ๐Ÿ› ๏ธ Developer Experience
Modern HTTP Client Token Management Type-Safe Responses
Smart Response Handling Auto Token Refresh Comprehensive Testing
Intelligent Caching Request Authentication Built-in Mocking
Auto-Retry Logic Secure Token Storage Detailed Logging
๐ŸŒ Platform ๐Ÿ“Š Performance ๐Ÿ”ง Advanced
Universal Support Request Metrics GraphQL Support
Web Compatible Rate Limiting File Operations
Cross-Platform Network Awareness Pagination Utils
WASM Ready Connection Pooling JSON Utilities

๐ŸŽฏ Key Capabilities #

  • ๐Ÿš€ Modern HTTP Client: Enhanced Dio with production-grade features
  • ๐Ÿ”„ Smart Response Handling: Automatic conversion to strongly-typed models
  • ๐Ÿ’พ Intelligent Caching: Configurable TTL with automatic invalidation
  • ๐Ÿ”‘ Token Management: Robust authentication with automatic refresh
  • ๐Ÿ” Auto-Retry: Configurable retry logic with exponential backoff
  • โšก Rate Limiting: Built-in throttling to prevent API abuse
  • ๐Ÿ“ถ Network Awareness: Automatic connectivity change handling
  • ๐Ÿ“Š Request Metrics: Built-in performance tracking and analytics
  • ๐Ÿ” Detailed Logging: Complete request/response logging with cURL commands
  • ๐Ÿ“„ Pagination Support: Utilities for handling paginated API responses
  • ๐Ÿ›ก๏ธ Type Safety: Strong typing throughout the entire library
  • ๐ŸŽฏ Error Handling: Comprehensive error handling with typed responses
  • ๐Ÿงช Mock Support: Built-in mocking system for testing without real HTTP calls
  • ๐Ÿ”— GraphQL Support: Native GraphQL queries, mutations, and subscriptions
  • ๐Ÿ“ File Operations: Easy file upload/download with progress tracking
  • ๐Ÿ”ง Extensible Architecture: Plugin-based design for custom functionality

๐ŸŽฏ Platform Support #

๐ŸŒ Universal Flutter Support - Write Once, Run Everywhere #

Platform Support File Operations Network Checking WASM Compatible
๐Ÿ“ฑ iOS โœ… Full โœ… Complete โœ… Native โœ… Ready
๐Ÿค– Android โœ… Full โœ… Complete โœ… Native โœ… Ready
๐ŸŒ Web โœ… Full ๐Ÿ”„ Bytes Only* โœ… HTTP-based โœ… Compatible
๐ŸชŸ Windows โœ… Full โœ… Complete โœ… Native โœ… Ready
๐ŸŽ macOS โœ… Full โœ… Complete โœ… Native โœ… Ready
๐Ÿง Linux โœ… Full โœ… Complete โœ… Native โœ… Ready

๐Ÿ’ก Web Platform Note: File operations use Uint8List instead of File objects due to browser security restrictions. This ensures maximum compatibility while maintaining functionality.

๐Ÿ“ฆ Installation #

Get started in seconds with a single dependency #

๐Ÿ“‹ Add Dependency #

dependencies:
  dio_flow: ^1.3.3

๐Ÿ”„ Install #

flutter pub get

๐Ÿ“ฑ Import #

import 'package:dio_flow/dio_flow.dart';

๐Ÿ“ฆ Development Dependencies (Optional)

For enhanced development experience:

dev_dependencies:
  dio_flow: ^1.3.3
  # For testing with mocks
  mockito: ^5.4.0
  # For integration testing
  integration_test:
    sdk: flutter

๐Ÿš€ Getting Started #

โšก From zero to API calls in under 2 minutes #

๐ŸŽฏ Quick Setup #

import 'package:dio_flow/dio_flow.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // ๐Ÿ”ง Configure Dio Flow
  DioFlowConfig.initialize(
    baseUrl: 'https://api.example.com',
    connectTimeout: const Duration(seconds: 30),
    receiveTimeout: const Duration(seconds: 30),
    sendTimeout: const Duration(seconds: 30),
  );

  // ๐Ÿš€ Initialize the client
  await ApiClient.initialize();

  runApp(MyApp());
}

๐ŸŽฏ Your First API Call #

// ๐Ÿ“ก Make your first request
final response = await DioRequestHandler.get('users');

if (response is SuccessResponseModel) {
  print('โœ… Success: ${response.data}');
} else {
  print('โŒ Error: ${response.error?.message}');
}

๐Ÿ”ง Advanced Configuration #

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // ๐Ÿ”ง Advanced configuration
  DioFlowConfig.initialize(
    baseUrl: 'https://api.example.com',
    connectTimeout: const Duration(seconds: 30),
    receiveTimeout: const Duration(seconds: 30),
    sendTimeout: const Duration(seconds: 30),

    // ๐Ÿ” Enable detailed logging
    debugMode: true,

    // ๐Ÿ”’ Security headers
    defaultHeaders: {
      'User-Agent': 'MyApp/1.0.0',
      'Accept': 'application/json',
    },

    // ๐Ÿ”„ Retry configuration
    retryOptions: RetryOptions(
      maxAttempts: 3,
      retryInterval: const Duration(seconds: 2),
    ),
  );

  // ๐Ÿ”‘ Initialize token management
  await TokenManager.initialize();

  // ๐Ÿš€ Initialize API client
  await ApiClient.initialize();

  runApp(MyApp());
}

๐ŸŽฏ Core Components #

DioRequestHandler #

The main class for making HTTP requests:

// GET request
final response = await DioRequestHandler.get(
  'users',
  parameters: {'role': 'admin'},
  requestOptions: RequestOptionsModel(
    hasBearerToken: true,
    shouldCache: true,
    retryOptions: RetryOptions(
      maxAttempts: 3,
      retryInterval: const Duration(seconds: 1),
    ),
  ),
);

// POST request with typed response
final loginResponse = await DioRequestHandler.post<LoginResponse>(
  'auth/login',
  data: {
    'email': 'user@example.com',
    'password': '********',
  },
  requestOptions: RequestOptionsModel(
    hasBearerToken: false,
  ),
);

Response Models #

All responses are wrapped in typed models:

if (response is SuccessResponseModel) {
  final data = response.data;
  // Handle success
} else {
  final error = response.error;
  switch (error.errorType) {
    case ErrorType.network:
      // Handle network error
      break;
    case ErrorType.validation:
      // Handle validation error
      break;
    case ErrorType.unauthorized:
      // Handle auth error
      break;
    // ... handle other error types
  }
}

Interceptors #

The package includes several built-in interceptors:

  1. MetricsInterceptor: Tracks request performance
  2. RateLimitInterceptor: Prevents API throttling
  3. DioInterceptor: Handles authentication and headers
  4. RetryInterceptor: Manages request retries
  5. ConnectivityInterceptor: Handles network state
  6. CacheInterceptor: Manages response caching

๐Ÿ”‘ Authentication #

๐Ÿ›ก๏ธ Enterprise-grade authentication with automatic token management #

Dio Flow provides a comprehensive authentication system with persistent storage, automatic token refresh, and seamless integration:

// Initialize token manager (call this in your main.dart)
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await TokenManager.initialize();

  // Register refresh logic (consumer-side). Optional โ€” if you don't set it,
  // automatic refresh will be disabled and TokenManager will return null on expired token.
    TokenManager.setRefreshHandler((refreshToken) async {
    // Use DioRequestHandler to call refresh endpoint (consumer controls endpoint details).
    final refreshResp = await DioRequestHandler.post(
      'auth/refresh',
      data: {'refresh_token': refreshToken},
    );

    if (refreshResp is! SuccessResponseModel) {
      throw ApiException('Refresh failed: ${refreshResp.error?.message ?? 'unknown'}');
    }

    final data = refreshResp.data!;
    final expiresIn = (data['expires_in'] as int?) ?? 3600;

    return RefreshTokenResponse(
      accessToken: data['access_token'] as String,
      refreshToken: data['refresh_token'] as String,
      expiry: DateTime.now().add(Duration(seconds: expiresIn)),
    );
  });

  runApp(MyApp());
}

// Setting tokens with persistence
await TokenManager.setTokens(
  accessToken: 'your_access_token',
  refreshToken: 'your_refresh_token',
  expiry: DateTime.now().add(Duration(hours: 1)),
);

// Check presence/validity (auto-refresh performed if expired and handler is set)
final hasToken = await TokenManager.hasAccessToken(); // returns true/false

// Getting access token (will automatically refresh if expired and a handler is configured)
final token = await TokenManager.getAccessToken(); // can be null if no handler and expired

// Clearing tokens
await TokenManager.clearTokens();

Key features:

  • Persistent token storage using SharedPreferences (tokens survive app restarts).

  • RefreshTokenHandler typedef โ€” consumer provides a small callback that receives the refresh token and returns a RefreshTokenResponse (access, refresh, expiry). This keeps the package network-agnostic.

  • TokenManager.setRefreshHandler(...) โ€” register refresh logic at startup or runtime (optional).

  • Automatic refresh behavior โ€” hasAccessToken() and getAccessToken() will automatically attempt to refresh when the access token is expired only if a refresh handler has been set. If no handler is provided, expired tokens are treated as absent (methods return false/null).

-Single-flight refresh protection โ€” internal _refreshCompleter ensures only one refresh request runs at a time; concurrent callers wait for that single result.

  • Tokens returned by the refresh handler are persisted via setTokens() (keeps state consistent across restarts).

  • All token operations are asynchronous for non-blocking startup and safer IO.

  • getAccessToken() behavior is unified: it either returns a valid token, triggers refresh (if handler exists), or returns null (if expired and no handler).

Protected Requests #

// Make authenticated request
final response = await DioRequestHandler.get(
  'user/profile',
  requestOptions: RequestOptionsModel(
    hasBearerToken: true, // This will automatically include the token
  ),
);

// Handle token expiration
if (response.error?.errorType == ErrorType.unauthorized) {
  // Token expired, handle refresh or logout
}

๐ŸŒ Endpoint Configuration #

Basic Endpoints #

// Register endpoints
EndpointProvider.instance.register('login', '/auth/login');
EndpointProvider.instance.register('users', '/api/users');

// Use registered endpoints
final response = await DioRequestHandler.post(
  'login',
  data: {'email': email, 'password': password},
);

Dynamic Endpoints #

// Register endpoint with parameters
EndpointProvider.instance.register('user_details', '/api/users/{id}');

// Use with path parameters
final response = await DioRequestHandler.get(
  'user_details',
  pathParameters: {'id': '123'},
);

๐Ÿ”„ Advanced Features #

Caching #

// Enable caching for a request
final response = await DioRequestHandler.get(
  'users',
  requestOptions: RequestOptionsModel(
    shouldCache: true,
    cacheMaxAge: const Duration(minutes: 5),
  ),
);

// Clear cache
await ApiClient.clearCache();

Pagination #

// Using pagination utilities
final paginatedResponse = await DioRequestHandler.get(
  'posts',
  parameters: {
    'page': 1,
    'per_page': 20,
  },
);

final pagination = PaginationHelper.fromResponse(paginatedResponse);
final hasMore = pagination.hasNextPage;
final totalPages = pagination.totalPages;

JSON Utilities #

// Safe JSON parsing
final jsonData = JsonUtils.tryParseJson(rawJson);

// Access nested values safely
final nestedValue = JsonUtils.getNestedValue(
  jsonData,
  'user.profile.name',
  'Default Name',
);

Request Queueing #

// Queue multiple requests
final responses = await Future.wait([
  DioRequestHandler.get('users'),
  DioRequestHandler.get('posts'),
  DioRequestHandler.get('comments'),
]);

// Handle rate limiting automatically
final rateLimitedResponse = await DioRequestHandler.get(
  'high-frequency-endpoint',
  requestOptions: RequestOptionsModel(
    shouldRateLimit: true,
    rateLimit: 30, // requests per minute
  ),
);

Custom Response Types #

class PaginatedResponse<T> {
  final List<T> items;
  final int total;
  final int page;

  PaginatedResponse.fromJson(
    Map<String, dynamic> json,
    T Function(Map<String, dynamic>) converter,
  )   : items = (json['data'] as List)
            .map((item) => converter(item))
            .toList(),
        total = json['total'] ?? 0,
        page = json['page'] ?? 1;
}

// Use with typed response
final response = await DioRequestHandler.get<PaginatedResponse<User>>(
  'users',
  converter: (json) => PaginatedResponse.fromJson(
    json,
    (item) => User.fromJson(item),
  ),
);

๐Ÿ› ๏ธ Best Practices #

๐Ÿ’ก Production-tested patterns for robust API integration #

๐Ÿš€ Essential Patterns #

1. Initialize Early

void main() async {
  await ApiClient.initialize();
  // ... rest of your app initialization
}

2. Handle Errors Consistently

try {
  final response = await DioRequestHandler.get('endpoint');
  if (response is SuccessResponseModel) {
    // Handle success
  } else {
    // Use the typed error handling
    handleError(response.error);
  }
} catch (e) {
  // Handle unexpected errors
}

3. Use Type-Safe Responses

class UserResponse {
  final String id;
  final String name;

  UserResponse.fromJson(Map<String, dynamic> json)
      : id = json['id'],
        name = json['name'];
}

final response = await DioRequestHandler.get<UserResponse>(
  'users/me',
  converter: (json) => UserResponse.fromJson(json),
);

Error Handling Patterns #

// Create a reusable error handler
Future<T> handleApiResponse<T>(ResponseModel response) async {
  if (response is SuccessResponseModel) {
    return response.data as T;
  }

  switch (response.error?.errorType) {
    case ErrorType.network:
      throw NetworkException(response.error!.message);
    case ErrorType.unauthorized:
      await handleUnauthorized();
      throw AuthException(response.error!.message);
    case ErrorType.validation:
      throw ValidationException(response.error!.message);
    default:
      throw ApiException(response.error?.message ?? 'Unknown error');
  }
}

// Use in your code
try {
  final users = await handleApiResponse<List<User>>(
    await DioRequestHandler.get('users'),
  );
  // Use users data
} on NetworkException catch (e) {
  // Handle network error
} on AuthException catch (e) {
  // Handle auth error
} on ValidationException catch (e) {
  // Handle validation error
} on ApiException catch (e) {
  // Handle other API errors
}

๐Ÿ—๏ธ Repository Pattern #

class UserRepository {
  Future<User> getCurrentUser() async {
    final response = await DioRequestHandler.get<User>(
      'users/me',
      requestOptions: RequestOptionsModel(
        hasBearerToken: true,
        shouldCache: true,
        cacheMaxAge: const Duration(minutes: 5),
      ),
      converter: (json) => User.fromJson(json),
    );

    return handleApiResponse<User>(response);
  }

  Future<void> updateProfile(UserUpdateRequest request) async {
    final response = await DioRequestHandler.put(
      'users/me',
      data: request.toJson(),
      requestOptions: RequestOptionsModel(hasBearerToken: true),
    );

    await handleApiResponse(response);
  }
}

โšก Performance Tips #

๐Ÿš€ Optimization strategies for production apps

// ๐Ÿ’พ Use caching strategically
final response = await DioRequestHandler.get(
  'static-data',
  requestOptions: RequestOptionsModel(
    shouldCache: true,
    cacheMaxAge: const Duration(hours: 1), // Cache static data longer
  ),
);

// ๐Ÿ”„ Batch requests when possible
final futures = [
  DioRequestHandler.get('users'),
  DioRequestHandler.get('posts'),
  DioRequestHandler.get('comments'),
];
final responses = await Future.wait(futures);

// โšก Use pagination for large datasets
final paginatedResponse = await PaginationUtils.fetchAllPages(
  'large-dataset',
  parameters: {'per_page': 50}, // Optimal page size
  maxPages: 10, // Limit to prevent memory issues
);

// ๐ŸŽฏ Optimize file uploads
final uploadResponse = await FileHandler.uploadBytes(
  'upload',
  compressedBytes, // Compress before upload
  'file.jpg',
  onProgress: (sent, total) {
    // Update UI efficiently
    if (sent % 1024 == 0) { // Update every KB
      updateProgressUI(sent / total);
    }
  },
);

๐Ÿงช Mock Support #

๐ŸŽญ Powerful mocking system for comprehensive testing #

Dio Flow includes a sophisticated mocking system that makes testing your API integrations effortless:

void main() {
  // Enable mock mode
  MockDioFlow.enableMockMode();

  // Register mock responses
  MockDioFlow.mockResponse(
    'users',
    MockResponse.success([
      {'id': 1, 'name': 'John Doe'},
      {'id': 2, 'name': 'Jane Smith'},
    ]),
  );

  // Register response queue for testing pagination
  MockDioFlow.mockResponseQueue('posts', [
    MockResponse.success({'page': 1, 'data': [...]}),
    MockResponse.success({'page': 2, 'data': [...]}),
  ]);

  // Your tests will now use mocked responses
  final response = await DioRequestHandler.get('users');

  // Disable mock mode
  MockDioFlow.disableMockMode();
}

๐Ÿ”— GraphQL Support #

โšก Native GraphQL integration with powerful query building #

Dio Flow provides first-class GraphQL support with an intuitive query builder and comprehensive operation handling:

// Simple query
final response = await GraphQLHandler.query('''
  query GetUser($id: ID!) {
    user(id: $id) {
      id
      name
      email
    }
  }
''', variables: {'id': '123'});

// Using query builder
final query = GraphQLQueryBuilder.query()
    .operationName('GetUsers')
    .variables({'first': 'Int'})
    .body('users(first: $first) { id name }')
    .build();

// Mutations
final mutationResponse = await GraphQLHandler.mutation('''
  mutation CreateUser($input: CreateUserInput!) {
    createUser(input: $input) {
      id
      name
    }
  }
''', variables: {'input': {'name': 'John', 'email': 'john@example.com'}});

// Batch operations
final operations = [
  GraphQLOperation(query: 'query { users { id } }'),
  GraphQLOperation(query: 'query { posts { id } }'),
];
final batchResponse = await GraphQLHandler.batch(operations);

๐Ÿ“ File Operations #

๐Ÿ“ค๐Ÿ“ฅ Seamless file handling across all platforms with progress tracking #

Dio Flow provides comprehensive file operations that work consistently across all Flutter platforms, with intelligent platform-specific optimizations:

Mobile/Desktop Platforms (iOS, Android, Windows, macOS, Linux) #

// File upload from File object
final file = File('/path/to/file.jpg');
final uploadResponse = await FileHandler.uploadFile(
  'upload',
  file,
  fieldName: 'avatar',
  additionalData: {'userId': '123'},
  onProgress: (sent, total) {
    print('Upload: ${(sent/total*100).toStringAsFixed(1)}%');
  },
);

// File download to disk
final downloadResponse = await FileHandler.downloadFile(
  'files/123/download',
  '/local/path/file.pdf',
  onProgress: (received, total) {
    print('Download: ${(received/total*100).toStringAsFixed(1)}%');
  },
);

Web Platform #

// Upload from bytes (web-compatible)
final bytesUploadResponse = await FileHandler.uploadBytes(
  'upload',
  fileBytes, // Uint8List
  'filename.jpg',
  fieldName: 'avatar',
  additionalData: {'userId': '123'},
);

// Download as bytes (web-compatible)
final bytesResponse = await FileHandler.downloadBytes('files/123');
if (bytesResponse is SuccessResponseModel) {
  final bytes = bytesResponse.data['bytes'] as Uint8List;
  // Use bytes for web download (e.g., trigger browser download)
}

Cross-Platform File Operations #

// Multiple file upload (use bytes for web compatibility)
final files = {
  'document': documentBytes, // Uint8List for web
  'image': imageBytes,       // Uint8List for web
};
final multiUploadResponse = await FileHandler.uploadMultipleFiles(
  'upload-multiple',
  files,
);

// Upload from bytes (works on all platforms)
final bytesUploadResponse = await FileHandler.uploadBytes(
  'upload',
  fileBytes,
  'filename.jpg',
);

Note: On web platform, direct file system access is restricted by browser security. Use FileHandler.uploadBytes() and FileHandler.downloadBytes() for web-compatible file operations.

๐Ÿ” Troubleshooting #

๐Ÿ› ๏ธ Quick solutions to common issues #

๐Ÿšจ Common Issues & Solutions #

  1. Authentication Issues:

    • Ensure hasBearerToken is set correctly in RequestOptionsModel
    • Check if tokens are properly managed in TokenManager
  2. Caching Problems:

    • Verify shouldCache is enabled in request options
    • Check cache duration settings
    • Try clearing cache with ApiClient.clearCache()
  3. Network Errors:

    • Check connectivity status
    • Verify retry options are configured
    • Examine cURL logs for request details
  4. Mock Issues:

    • Ensure MockDioFlow.enableMockMode() is called before requests
    • Verify mock responses are registered for the correct endpoints
    • Check that endpoint paths match exactly
  5. GraphQL Errors:

    • Validate GraphQL syntax in queries
    • Check that variables match the schema
    • Ensure the GraphQL endpoint is correctly configured
  6. File Upload Issues:

    • Verify file permissions and paths
    • Check server file size limits
    • Ensure correct Content-Type headers for multipart uploads

๐Ÿ” Debug Mode #

// Enable detailed logging
DioFlowConfig.initialize(
  baseUrl: 'https://api.example.com',
  debugMode: true, // This will enable detailed logging
);

// Log specific requests
final response = await DioRequestHandler.get(
  'users',
  requestOptions: RequestOptionsModel(
    shouldLogRequest: true, // Log this specific request
  ),
);

๐Ÿ“š Quick Reference #

โšก Common operations at a glance #

๐Ÿ”— API Calls Cheat Sheet

// GET request
final users = await DioRequestHandler.get('users');

// POST with data
final created = await DioRequestHandler.post('users', data: userData);

// PUT update
final updated = await DioRequestHandler.put('users/123', data: updates);

// DELETE
final deleted = await DioRequestHandler.delete('users/123');

// With authentication
final profile = await DioRequestHandler.get(
  'profile',
  requestOptions: RequestOptionsModel(hasBearerToken: true),
);

// With caching
final cached = await DioRequestHandler.get(
  'static-data',
  requestOptions: RequestOptionsModel(
    shouldCache: true,
    cacheMaxAge: Duration(minutes: 30),
  ),
);

๐Ÿ”‘ Authentication Cheat Sheet

// Set tokens
await TokenManager.setTokens(
  accessToken: 'access_token',
  refreshToken: 'refresh_token',
  expiry: DateTime.now().add(Duration(hours: 1)),
);

// Check if authenticated
final isAuthenticated = await TokenManager.hasAccessToken();

// Get current token (auto-refreshes if needed)
final token = await TokenManager.getAccessToken();

// Clear tokens (logout)
await TokenManager.clearTokens();

๐Ÿ“ File Operations Cheat Sheet

// Upload file (mobile/desktop)
final upload = await FileHandler.uploadFile('upload', file);

// Upload bytes (all platforms)
final upload = await FileHandler.uploadBytes('upload', bytes, 'file.jpg');

// Download file (mobile/desktop)
final download = await FileHandler.downloadFile('files/123', '/path/file.pdf');

// Download bytes (all platforms)
final download = await FileHandler.downloadBytes('files/123');

๐Ÿงช Testing Cheat Sheet

// Enable mocking
MockDioFlow.enableMockMode();

// Mock success response
MockDioFlow.mockResponse('users', MockResponse.success([...]));

// Mock error response
MockDioFlow.mockResponse('users', MockResponse.failure('Error message'));

// Mock network error
MockDioFlow.mockResponse('users', MockResponse.networkError());

// Disable mocking
MockDioFlow.disableMockMode();

๐Ÿค Contributing #

We love contributions! Help make Dio Flow even better ๐Ÿ’ช #

Contributions are welcome! Whether it's:

  • ๐Ÿ› Bug Reports: Found an issue? Let us know!
  • โœจ Feature Requests: Have an idea? We'd love to hear it!
  • ๐Ÿ“– Documentation: Help improve our docs
  • ๐Ÿ”ง Code Contributions: Submit a PR!

Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.

๐ŸŒŸ Contributors #

Thanks to all our amazing contributors who help make Dio Flow better!


๐Ÿ“„ License #

๐Ÿ“œ MIT License - Free for everyone, everywhere #

This project is licensed under the MIT License - see the LICENSE file for details.

Made with โค๏ธ by the Flutter community


๐ŸŒŸ Star us on GitHub if Dio Flow helped you #

GitHub stars

Happy coding! ๐Ÿš€

4
likes
150
points
419
downloads

Publisher

verified publishermoeinmoradi.ir

Weekly Downloads

Flexible HTTP client for Flutter, built on Dio with mock support, GraphQL, file handling, caching, and token management.

Repository (GitHub)
View/report issues

Documentation

Documentation
API reference

License

MIT (license)

Dependencies

colorful_log_plus, dio, flutter, log_curl_request, shared_preferences

More

Packages that depend on dio_flow