संबंधित सोर्स रिपॉज़िटरी के मूल README का स्नैपशॉट। नवीनतम सामग्री के लिए रिपॉज़िटरी देखें।
Flutter SmartDio
🚀 Features
🔌 Transport-Agnostic Design
Works with ANY HTTP client : Dio, http package, Chopper, dart:io HttpClient
Unified API across all transport layers
Easy client switching without changing your code
Adapter pattern for extensibility
💾 Persistent Caching
Hive-based storage that survives app restarts
Intelligent TTL management with automatic expiry
Cache policies : Network-first, Cache-first, Cache-only, Network-only
Real-time cache statistics and analytics
🔄 Smart Retry & Resilience
Exponential backoff with configurable delays
Custom retry policies for different scenarios
Request deduplication to prevent duplicate calls
Never-crash philosophy with structured error handling
📱 Offline-First Architecture
Persistent request queuing with Hive storage that survives app restarts
Configurable storage options : persistent, memory-only, or disabled
Automatic queue processing when connectivity returns
Connectivity monitoring with quality assessment
Seamless online/offline transitions
📊 Advanced Monitoring
Performance metrics with response time tracking
Success rate analytics and failure reporting
Enhanced response logging that shows actual object data instead of "Instance of Object"
Dual logging : raw JSON response + transformed object data
Smart object serialization with automatic toJson() detection
Colorized debug logging with syntax-highlighted JSON and headers
Comprehensive logging with sensitive data protection
Real-time event streaming for monitoring
🎯 Developer Experience
Type-safe responses with sealed classes
Clean architecture with dependency injection
Minimal configuration required
Extensive documentation and examples
📦 Installation
Add this to your package's pubspec.yaml file:
dependencies:
flutter_smartdio: ^1.0.4
Then run:
flutter pub get
⚡ Quick Start
1. Basic Setup
import 'package:flutter_smartdio/flutter_smartdio.dart' ;
final client = SmartDioClient (
adapter: HttpClientAdapterImpl (),
config: const SmartDioConfig (
defaultTimeout: Duration (seconds: 30 ),
cachePolicy: CachePolicy .networkFirst (
ttl: Duration (minutes: 5 ),
),
enableMetrics: true ,
enableRequestQueue: true ,
queueStorageType: QueueStorageType .persistent,
),
cacheStore: HiveCacheStore (),
);
import 'package:dio/dio.dart' ;
final dioClient = SmartDioClient (
adapter: DioClientAdapter (dioInstance: Dio ()),
config: const SmartDioConfig (
defaultTimeout: Duration (seconds: 30 ),
retryPolicy: RetryPolicy .exponentialBackoff (
maxAttempts: 3 ,
initialDelay: Duration (milliseconds: 500 ),
),
cachePolicy: CachePolicy .networkFirst (ttl: Duration (minutes: 10 )),
logLevel: LogLevel .debug,
enableMetrics: true ,
enableDeduplication: true ,
enableRequestQueue: true ,
queueStorageType: QueueStorageType .persistent,
maxQueueSize: 100 ,
maxQueueAge: Duration (days: 7 ),
),
cacheStore: HiveCacheStore (),
);
2. Making Requests
final response = await client.get <User >(
'https://jsonplaceholder.typicode.com/users/1' ,
transformer: (data) => User .fromJson (data as Map <String , dynamic >),
);
response.fold (
(success) => print ('User: ${success.data.name} ' ),
(error) => print ('Error: ${error.error} ' ),
);
final postResponse = await client.post<Map <String , dynamic >>(
'https://jsonplaceholder.typicode.com/posts' ,
body: {'title' : 'Hello World' , 'body' : 'Test content' , 'userId' : 1 },
config: const RequestConfig (
cachePolicy: CachePolicy .networkFirst (ttl: Duration (hours: 1 )),
),
transformer: (data) => data as Map <String , dynamic >,
);
final putResponse = await client.put<Post >(
'https://jsonplaceholder.typicode.com/posts/1' ,
body: updatedPost.toJson (),
transformer: (data) => Post .fromJson (data as Map <String , dynamic >),
);
final patchResponse = await client.patch<Post >(
'https://jsonplaceholder.typicode.com/posts/1' ,
body: {'title' : 'Updated Title' },
transformer: (data) => Post .fromJson (data as Map <String , dynamic >),
);
final deleteResponse = await client.delete<Map <String , dynamic >>(
'https://jsonplaceholder.typicode.com/posts/1' ,
transformer: (data) => data as Map <String , dynamic >? ?? {},
);
3. Switch HTTP Clients Seamlessly
final client = SmartDioClient (
adapter: HttpClientAdapterImpl (),
config: const SmartDioConfig (
defaultTimeout: Duration (seconds: 30 ),
enableMetrics: true ,
),
);
await client.dispose ();
import 'package:dio/dio.dart' ;
final newClient = SmartDioClient (
adapter: DioClientAdapter (dioInstance: Dio ()),
config: const SmartDioConfig (
defaultTimeout: Duration (seconds: 30 ),
enableMetrics: true ,
),
);
import 'package:http/http.dart' as http;
final httpPackageClient = SmartDioClient (
adapter: HttpPackageAdapter (httpClient: http.Client ()),
config: const SmartDioConfig (
defaultTimeout: Duration (seconds: 30 ),
enableMetrics: true ,
),
);
import 'package:chopper/chopper.dart' ;
final chopperClient = SmartDioClient (
adapter: ChopperClientAdapter (client: ChopperClient ()),
config: const SmartDioConfig (
defaultTimeout: Duration (seconds: 30 ),
enableMetrics: true ,
),
);
🏗️ Supported HTTP Clients
Client
Adapter Class
Package
dart:io HttpClient
HttpClientAdapterImpl
Built-in (Default)
Dio
DioClientAdapter
dio: ^5.8.0
HTTP Package
HttpPackageAdapter
http: ^1.4.0
Chopper
ChopperClientAdapter
chopper: ^8.3.0
🎛️ Configuration Options
Cache Policies
CachePolicy .networkFirst (ttl: Duration (minutes: 5 ))
CachePolicy .cacheFirst (ttl: Duration (hours: 1 ))
CachePolicy .cacheOnly ()
CachePolicy .networkOnly ()
CachePolicy .none ()
Retry Policies
const RetryPolicy .exponentialBackoff (
maxAttempts: 3 ,
initialDelay: Duration (milliseconds: 500 ),
multiplier: 2.0 ,
jitter: true ,
)
const RetryPolicy .fixed (
maxAttempts: 3 ,
delay: Duration (seconds: 1 ),
)
final RetryPolicy .custom (
maxAttempts: 5 ,
delayCalculator: (attempt) => Duration (seconds: attempt * 2 ),
shouldRetry: (error) => error.type == SmartDioErrorType .network,
)
const RetryPolicy .none ()
Queue Storage Options
SmartDioConfig (
queueStorageType: QueueStorageType .persistent,
maxQueueSize: 100 ,
maxQueueAge: Duration (days: 7 ),
)
SmartDioConfig (
queueStorageType: QueueStorageType .memory,
maxQueueSize: 50 ,
)
SmartDioConfig (
queueStorageType: QueueStorageType .none,
enableRequestQueue: false ,
)
Enhanced Debug Logging
SmartDioConfig (
logLevel: LogLevel .debug,
)
📊 Monitoring & Analytics
client.metrics.events.listen ((event) {
switch (event) {
case RequestCompletedEvent (:final metrics):
print ('Request took: ${metrics.totalDuration.inMilliseconds} ms' );
print ('Success: ${metrics.success} ' );
break ;
case CacheHitEvent ():
print ('Cache hit occurred' );
break ;
case CacheMissEvent ():
print ('Cache miss occurred' );
break ;
}
});
final cacheMetrics = client.metrics.getCacheMetrics ();
print ('Cache hit rate: ${(cacheMetrics.hitRate * 100 ).toStringAsFixed(1 )} %' );
print ('Cache hits: ${cacheMetrics.hitCount} ' );
print ('Cache misses: ${cacheMetrics.missCount} ' );
final successRate = client.metrics.getSuccessRate ();
print ('Overall success rate: ${(successRate * 100 ).toStringAsFixed(1 )} %' );
final avgResponseTime = client.metrics.getAverageResponseTime ();
print ('Average response time: ${avgResponseTime.inMilliseconds} ms' );
final queueMetrics = client.metrics.getQueueMetrics (client.queue.length);
print ('Queue size: ${queueMetrics.currentSize} ' );
print ('Queue processed: ${queueMetrics.totalProcessed} ' );
print ('Queue success rate: ${(queueMetrics.successRate * 100 ).toStringAsFixed(1 )} %' );
🎨 Enhanced Debug Logging
SmartDio includes a powerful, colorized logging system that provides detailed insights into your HTTP traffic. Perfect for development and debugging!
🌈 Colorized Console Output
When debug logging is enabled, you'll see beautiful, color-coded logs with:
📋 Headers - Blue keys, Green values, Red for sensitive data
📤 Request Payload - Syntax-highlighted JSON with proper indentation
📥 Response Body - Color-coded data types (strings, numbers, booleans)
🔒 Security - Sensitive data automatically redacted as [REDACTED]
🔧 Enable Debug Logging
There are two LogLevel settings that control different aspects of logging:
1. Framework-Level Logging (SmartDioConfig)
Controls internal client operations like cache hits, retries, queue operations:
final client = SmartDioClient (
adapter: DioClientAdapter (dioInstance: Dio ()),
config: const SmartDioConfig (
logLevel: LogLevel .debug,
enableMetrics: true ,
enableDeduplication: true ,
enableRequestQueue: true ,
),
);
2. HTTP Traffic Logging (SmartLogger)
Controls detailed HTTP request/response logging with headers, payloads, and response bodies:
final client = SmartDioClient (
adapter: DioClientAdapter (dioInstance: Dio ()),
logger: SmartLogger (level: LogLevel .debug),
config: const SmartDioConfig (
),
);
📊 Log Level Comparison
Aspect
SmartDioConfig.logLevel
SmartLogger.level
Scope
Client framework operations
HTTP traffic details
Controls
Cache, retry, queue logs
Headers, payloads, responses
Example Logs
"Cache hit", "Retrying request"
Request headers, JSON payloads
Performance Impact
Low
Higher (detailed HTTP data)
Security
General client info
Sensitive data (sanitized)
🎯 Recommended Settings
Development Mode
final client = SmartDioClient (
adapter: DioClientAdapter (dioInstance: Dio ()),
logger: SmartLogger (level: LogLevel .debug),
config: const SmartDioConfig (
logLevel: LogLevel .debug,
enableMetrics: true ,
),
);
Production Mode
final client = SmartDioClient (
adapter: DioClientAdapter (dioInstance: Dio ()),
logger: SmartLogger (level: LogLevel .warning),
config: const SmartDioConfig (
logLevel: LogLevel .warning,
enableMetrics: true ,
),
);
Performance Testing
final client = SmartDioClient (
adapter: DioClientAdapter (dioInstance: Dio ()),
logger: SmartLogger (level: LogLevel .error),
config: const SmartDioConfig (
logLevel: LogLevel .error,
enableMetrics: false ,
),
);
🎨 Example Debug Output
When both log levels are set to LogLevel.debug, you'll see output like:
🔧 [DEBUG] 📋 Request Headers:
content-type: application/json
authorization: [REDACTED]
user-agent: SmartDio Flutter App/1.0
🔧 [DEBUG] 📤 Request Payload:
{
"title" : "Hello World" ,
"body" : "Test content" ,
"userId" : 1,
"password" : "[REDACTED]"
}
✅ [INFO] HTTP Response: 201 POST /api/posts (245ms)
🔧 [DEBUG] 📋 Response Headers:
content-type: application/json; charset=utf-8
server: nginx/1.18.0
location: /api/posts/101
🔧 [DEBUG] 📥 Response Body:
{
"id" : 101,
"title" : "Hello World" ,
"body" : "Test content" ,
"userId" : 1,
"createdAt" : "2023-12-01T10:30:00Z"
}
🛡️ Security Features
Automatic Sanitization : Sensitive headers and body fields are automatically redacted
Configurable Sensitive Fields :
Headers: authorization, x-api-key, cookie, x-auth-token
Body: password, token, secret, key, authorization
Nested Object Support : Deep sanitization of complex JSON structures
Performance Optimized : Colors only applied when using ColorfulConsoleLogSink
🎛️ Custom Logger Configuration
final basicLogger = SmartLogger .basic (level: LogLevel .debug);
final compactLogger = SmartLogger .compact (level: LogLevel .debug);
final customLogger = SmartLogger (
level: LogLevel .debug,
sensitiveHeaders: ['custom-auth' , 'x-secret' ],
sensitiveBodyFields: ['customPassword' , 'apiKey' ],
sinks: [ColorfulConsoleLogSink (
enableColors: true ,
enableEmojis: true ,
compactMode: false ,
)],
);
🔧 Advanced Usage
Custom Error Handling
final response = await client.get <Data >('/api/data' ,
transformer: (data) => Data .fromJson (data),
);
response.fold (
(success) {
final data = success.data;
final fromCache = success.isFromCache;
final statusCode = success.statusCode;
},
(error) {
switch (error.type) {
case SmartDioErrorType .network:
showNetworkError ();
break ;
case SmartDioErrorType .timeout:
showTimeoutError ();
break ;
case SmartDioErrorType .badResponse:
showServerError (error.statusCode);
break ;
}
},
);
Offline Queue Management
final client = SmartDioClient (
adapter: HttpClientAdapterImpl (),
config: const SmartDioConfig (
enableRequestQueue: true ,
maxQueueSize: 100 ,
),
requestQueue: RequestQueue (
storage: MemoryQueueStorage (),
maxSize: 50 ,
),
);
client.queue.events.listen ((event) {
switch (event) {
case QueueItemAdded ():
print ('Request queued for later' );
break ;
case QueueItemRemoved ():
print ('Request removed from queue' );
break ;
case QueueItemFailed ():
print ('Queued request failed' );
break ;
}
});
client.connectivity.setManualOfflineMode (true );
client.connectivity.setManualOfflineMode (false );
final connectivityInfo = client.connectivity.currentStatus;
print ('Status: ${connectivityInfo.status} ' );
print ('Quality: ${connectivityInfo.quality} ' );
🧪 Testing
SmartDio is designed to be test-friendly with easy mocking:
class MockAdapter extends HttpClientAdapter {
final Map <String , dynamic > mockResponses;
MockAdapter (this .mockResponses);
@override
Future <SmartDioResponse <T>> execute<T>({
required SmartDioRequest request,
required T Function (dynamic data) transformer,
}) async {
final mockData = mockResponses[request.uri.toString ()];
if (mockData == null ) {
return SmartDioError <T>(
error: Exception ('No mock response found' ),
type: SmartDioErrorType .network,
correlationId: request.correlationId,
timestamp: DateTime .now (),
duration: Duration .zero,
);
}
return SmartDioSuccess <T>(
data: transformer (mockData),
statusCode: 200 ,
correlationId: request.correlationId,
timestamp: DateTime .now (),
duration: Duration (milliseconds: 100 ),
);
}
@override
Future <void > close () async {}
}
final mockClient = SmartDioClient (
adapter: MockAdapter ({
'https://api.example.com/users/1' : {
'id' : 1 ,
'name' : 'Test User' ,
'email' : 'test@example.com'
}
}),
config: const SmartDioConfig (),
);
final response = await mockClient.get <User >(
'https://api.example.com/users/1' ,
transformer: (data) => User .fromJson (data as Map <String , dynamic >),
);
📱 Example Apps
The package includes two comprehensive example apps:
Main Example (example/lib/main.dart)
Multi-HTTP client switching (Dio, HTTP, Chopper, dart:io HttpClient)
Interactive feature testing with live UI
Real-time performance metrics and analytics
Persistent cache management with Hive
Colorized debug logging with headers, payloads, and response bodies
Enhanced logging with security-safe sensitive data redaction
Offline mode simulation and queue management
Request deduplication testing
Type-safe API demonstrations
Simple API Demo (example/lib/example2.dart)
Clean API service implementation
All HTTP methods (GET, POST, PUT, PATCH, DELETE)
Type-safe model examples (User, Post, Comment)
Cache strategies demonstration
Error handling patterns
Performance metrics integration
cd example
flutter run lib/main.dart
flutter run lib/example2.dart
🏛️ Architecture
SmartDio uses clean architecture principles:
┌─────────────────────────────────────────┐
│ SmartDioClient │
├─────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Config │ │ Interceptors │ │
│ └─────────────┘ └─────────────────────┘ │
├─────────────────────────────────────────┤
│ ┌─────────────┐ ┌──────────┐ ┌────────┐ │
│ │ Cache │ │ Queue │ │ Logger │ │
│ └─────────────┘ └──────────┘ └────────┘ │
├─────────────────────────────────────────┤
│ HTTP Adapters │
│ ┌──────┐ ┌──────┐ ┌─────────┐ ┌──────┐ │
│ │ Dio │ │ HTTP │ │ Chopper │ │ dart │ │
│ └──────┘ └──────┘ └─────────┘ └──────┘ │
└─────────────────────────────────────────┘
🤝 Contributing
Contributions are welcome! Please read our Contributing Guide first.
Fork the repository
Create your feature branch (git checkout -b feature/amazing-feature)
Commit your changes (git commit -m 'Add amazing feature')
Push to the branch (git push origin feature/amazing-feature)
Open a Pull Request
🐛 Issues
If you encounter any issues, please create an issue with:
Flutter version
Dart version
SmartDio version
Minimal reproduction code
Error logs
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🙏 Acknowledgments
Inspired by the need for a universal HTTP solution in Flutter
Built with ❤️ for the Flutter community
Thanks to all HTTP client library authors for their excellent work
🔗 Links
Made with ❤️ by Rahul Shah
If you find this package helpful, please ⭐ the repository!