패키지, 저장소 및 앱 카테고리 검색

패키지 상세v1.0.4

flutter_smartdio

모든 HTTP 클라이언트에 오프라인 캐싱, 요청 대기열, 재시도 메커니즘 및 포괄적인 로깅 기능을 제공하는 전송 방식에 관계없는 HTTP 래퍼입니다.

AndroidiOSmacOSWindowsLinux
30일 다운로드
50
좋아요
17
Pub 점수
80

패키지 설치

flutter pub add flutter_smartdio

패키지 개요

공개 정보를 바탕으로 생성한 선택 가이드입니다.

flutter_smartdio는 어떤 HTTP 클라이언트라도 강력한 오프라인 캐싱, 요청 대기열, 자동 재시도 메커니즘 및 상세 로깅 기능을 통해 개선할 수 있도록 설계된 전송에 관계없는 HTTP 래퍼입니다. Dio 위에 구축되어 불안정한 환경에서도 신뢰할 수 있는 네트워크 작업을 보장합니다. 복잡한 네트워킹 로직을 추상화하여 플랫폼 간 일관된 요청과 응답 관리를 쉽게 만듭니다. 저연결 환경에서 높은 가용성과 회복력을 필요로 하는 앱에 적합합니다.

사용 사례

  • 오프라인 우선 애플리케이션
  • 고신뢰성 API 통신
  • 약한 연결 환경에서의 네트워크 회복력
  • 요청 배치 및 재시도 로직
  • 포괄적인 네트워크 디버깅
  • 크로스 플랫폼 HTTP 일관성

주요 기능

  • 오프라인 캐싱 지원
  • 다운타임 중 요청 대기열
  • 자동 재시도 및 백오프
  • 세부 로깅 기능
  • 운송 수단에 관계없는 설계
  • Dio 통합

적합한 대상

  • 오프라인 기능이 필요한 앱
  • 네트워크 신뢰성을 우선시하는 개발자
  • 요청 지속성이 필요한 프로젝트
  • 복잡한 API 워크플로를 관리하는 팀
  • 크로스플랫폼 모바일 및 데스크톱 앱

고려 사항

  • Dio 내부 구조 이해 필요
  • 큰 캐시를 사용할 경우 메모리 사용량이 증가할 수 있습니다
  • 로그 기록은 올바르게 구성되지 않으면 성능에 영향을 줄 수 있습니다
  • 독립적인 HTTP 클라이언트가 아니라 강화 도구입니다
  • 최적의 결과를 얻기 위해 상태 관리와 함께 사용하는 것이 가장 좋습니다

원본 README

연결된 소스 저장소의 README 원문 스냅샷입니다. 최신 내용은 저장소에서 확인하세요.

Flutter SmartDio

Flutter Dart License: MIT

A transport-agnostic HTTP wrapper that enhances ANY HTTP client with offline caching, request queuing, retry mechanisms, and comprehensive logging.

Features • Installation • Quick Start • Documentation • Example

🚀 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';

// Initialize with built-in dart:io HttpClient (default)
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, // Survives app restarts
  ),
  cacheStore: HiveCacheStore(), // Persistent cache
);

// Or use with Dio
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, // Enable detailed response logging
    enableMetrics: true,
    enableDeduplication: true,
    enableRequestQueue: true,
    queueStorageType: QueueStorageType.persistent, // Default, survives app restarts
    maxQueueSize: 100,
    maxQueueAge: Duration(days: 7),
  ),
  cacheStore: HiveCacheStore(),
);
2. Making Requests
// Type-safe GET request
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}'),
);

// POST request with caching
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>,
);

// All HTTP methods are supported
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
// Start with dart:io HttpClient
final client = SmartDioClient(
  adapter: HttpClientAdapterImpl(),
  config: const SmartDioConfig(
    defaultTimeout: Duration(seconds: 30),
    enableMetrics: true,
  ),
);

// Switch to Dio - same API!
await client.dispose();
import 'package:dio/dio.dart';
final newClient = SmartDioClient(
  adapter: DioClientAdapter(dioInstance: Dio()),
  config: const SmartDioConfig(
    defaultTimeout: Duration(seconds: 30),
    enableMetrics: true,
  ),
);

// Or use HTTP package
import 'package:http/http.dart' as http;
final httpPackageClient = SmartDioClient(
  adapter: HttpPackageAdapter(httpClient: http.Client()),
  config: const SmartDioConfig(
    defaultTimeout: Duration(seconds: 30),
    enableMetrics: true,
  ),
);

// Or use Chopper
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
// Network-first (default)
CachePolicy.networkFirst(ttl: Duration(minutes: 5))

// Cache-first (offline-friendly)
CachePolicy.cacheFirst(ttl: Duration(hours: 1))

// Cache-only (no network)
CachePolicy.cacheOnly()

// Network-only (no cache)
CachePolicy.networkOnly()

// No caching
CachePolicy.none()
Retry Policies
// Exponential backoff (default configuration)
const RetryPolicy.exponentialBackoff(
  maxAttempts: 3,
  initialDelay: Duration(milliseconds: 500),
  multiplier: 2.0,
  jitter: true,
)

// Fixed delay
const RetryPolicy.fixed(
  maxAttempts: 3,
  delay: Duration(seconds: 1),
)

// Custom retry logic
final RetryPolicy.custom(
  maxAttempts: 5,
  delayCalculator: (attempt) => Duration(seconds: attempt * 2),
  shouldRetry: (error) => error.type == SmartDioErrorType.network,
)

// No retry
const RetryPolicy.none()
Queue Storage Options
// Persistent storage (default) - survives app restarts
SmartDioConfig(
  queueStorageType: QueueStorageType.persistent,
  maxQueueSize: 100,
  maxQueueAge: Duration(days: 7),
)

// Memory-only storage - lost on app restart
SmartDioConfig(
  queueStorageType: QueueStorageType.memory,
  maxQueueSize: 50,
)

// Disable queuing entirely
SmartDioConfig(
  queueStorageType: QueueStorageType.none,
  enableRequestQueue: false,
)
Enhanced Debug Logging
// Enable detailed logging to see actual response data
SmartDioConfig(
  logLevel: LogLevel.debug, // Shows both raw JSON and transformed objects
)

// Example output:
// 📥 Raw Response Data:
// {
//   "id": 1,
//   "name": "John Doe",
//   "email": "john@example.com"
// }
// 🔄 Transformed Response:
// User(id: 1, name: John Doe, email: john@example.com)

📊 Monitoring & Analytics

// Listen to performance metrics
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;
  }
});

// Get real-time statistics
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');

// Get queue metrics
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,  // Framework operations logging
    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),  // HTTP traffic logging
  config: const SmartDioConfig(
    // ... other config
  ),
);
📊 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),  // Full HTTP details
  config: const SmartDioConfig(
    logLevel: LogLevel.debug,  // All framework details
    enableMetrics: true,
  ),
);
Production Mode
final client = SmartDioClient(
  adapter: DioClientAdapter(dioInstance: Dio()),
  logger: SmartLogger(level: LogLevel.warning),  // Errors only
  config: const SmartDioConfig(
    logLevel: LogLevel.warning,  // Framework errors only
    enableMetrics: true,
  ),
);
Performance Testing
final client = SmartDioClient(
  adapter: DioClientAdapter(dioInstance: Dio()),
  logger: SmartLogger(level: LogLevel.error),  // Minimal logging
  config: const SmartDioConfig(
    logLevel: LogLevel.error,  // Minimal logging
    enableMetrics: false,  // Disable for pure performance
  ),
);
🎨 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
// Basic logger (no colors/emojis)
final basicLogger = SmartLogger.basic(level: LogLevel.debug);

// Compact logger (minimal output)
final compactLogger = SmartLogger.compact(level: LogLevel.debug);

// Custom logger with specific settings
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) {
    // Handle success
    final data = success.data;
    final fromCache = success.isFromCache;
    final statusCode = success.statusCode;
  },
  (error) {
    // Handle different error types
    switch (error.type) {
      case SmartDioErrorType.network:
        showNetworkError();
        break;
      case SmartDioErrorType.timeout:
        showTimeoutError();
        break;
      case SmartDioErrorType.badResponse:
        showServerError(error.statusCode);
        break;
    }
  },
);
Offline Queue Management
// Enable offline queueing (enabled by default)
final client = SmartDioClient(
  adapter: HttpClientAdapterImpl(),
  config: const SmartDioConfig(
    enableRequestQueue: true,
    maxQueueSize: 100,
  ),
  requestQueue: RequestQueue(
    storage: MemoryQueueStorage(),
    maxSize: 50,
  ),
);

// Listen to queue events
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;
  }
});

// Manually control offline mode
client.connectivity.setManualOfflineMode(true);  // Force offline
client.connectivity.setManualOfflineMode(false); // Back online

// Check connectivity status
final connectivityInfo = client.connectivity.currentStatus;
print('Status: ${connectivityInfo.status}');
print('Quality: ${connectivityInfo.quality}');

🧪 Testing

SmartDio is designed to be test-friendly with easy mocking:

// Create a mock adapter for testing
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 {}
}

// Use in tests
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        # Interactive multi-client demo
# or
flutter run lib/example2.dart    # Simple API demo

🏛️ 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.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. 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!

카테고리

의존성

의존성 목록 7 개

소스 저장소

이 패키지를 사용하는 프로젝트

아직 데이터가 없습니다.