パッケージ、リポジトリ、アプリカテゴリを検索

パッケージ詳細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 件

ソースリポジトリ

このパッケージを使用しているプロジェクト

データはまだありません。