π ApiClientPlus
π₯ Enterprise-Grade HTTP Client with Blazing Fast Performance
Intelligent caching β’ Multi-API management β’ Zero memory leaks
Quick Start β’ Features β’ Docs β’ Examples
π― Why ApiClientPlus?
β‘ Blazing Fast~12ms overhead |
π¨ Developer FriendlyClean API design |
π’ Production ReadyExtensive testing |
β¨ Features
π― Core Capabilities
β Multi-API Configuration // Manage multiple endpoints seamlessly
β Intelligent Caching // 6 strategies with auto-expiration
β Token Authentication // Auto-refresh & error handling
β Request Interceptors // Transform requests/responses
β Error Fallback // Graceful cache fallback
β Comprehensive Logging // Debug with precision
π Cache Strategies
| Strategy | Behavior | Best For |
|---|---|---|
| π― cacheFirst | Cache β Network | General purpose APIs |
| π networkFirst | Network β Cache | Fresh data priority |
| πΎ cacheOnly | Cache exclusive | Offline-first apps |
| π΄ networkOnly | No caching | Real-time updates |
| β‘ staleWhileRevalidate | Instant + refresh | Performance critical |
| π cacheThenNetwork | Cache + background | Progressive loading |
π¦ Installation
Add to your pubspec.yaml:
dependencies:
api_client_plus: ^1.0.0
Install:
flutter pub get
π Quick Start
1οΈβ£ Initialize (One-Time Setup)
import 'package:api_client_plus/api_client_plus.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await ApiClientPlus().initialize(
configs: [
ApiConfig(
name: 'dev',
baseUrl: 'https://api.dev.example.com',
requiresAuth: true,
),
ApiConfig(
name: 'api',
baseUrl: 'https://api.example.com',
requiresAuth: true,
),
ApiConfig(
name: 'auth',
baseUrl: 'https://api.example.com',
requiresAuth: false,
),
],
defaultDomain: kReleaseMode ? 'prod' : 'dev',
cacheConfig: CacheConfig(
enableCache: true,
defaultTtl: Duration(minutes: 10),
),
logConfig: LogConfig(
showLog: kReleaseMode,
showCacheLog: false,
messageLimit: 300,
prettyJson: false,
isColored: true,
showCaller: false,
logStyle: LogStyle.minimal,
logLevel: "DEBUG",
),
tokenGetter: () async {
// final prefs = await SharedPreferences.getInstance();
// return prefs.getString('access_token');
return 'my_access_token';
},
onTokenInvalid: () async {
// Redirect logic here
},
onRequest: (options) async {
options.headers['User-Agent'] = 'MyApp/1.0.0';
},
onResponse: (response) async {
debugPrint('β
${response.statusCode} ${response.requestOptions.path}');
},
onError: (error) async {
debugPrint('β API Error: ${error.message}');
},
);
runApp(MyApp());
}
2οΈβ£ Make API Calls
// Simple GET request with caching
final response = await ApiClientService.get(
'/users',
useCache: true,
cacheStrategy: ApiClientCacheStrategy.cacheFirst,
);
// POST with authentication
final user = await ApiClientService.post(
'/users',
data: {'name': 'John Doe', 'email': 'john@example.com'},
);
// PUT/PATCH updates
await ApiClientService.put('/users/123', data: updatedData);
await ApiClientService.patch('/users/123', data: partialData);
// DELETE
await ApiClientService.delete('/users/123');
3οΈβ£ Handle Responses
try {
final response = await ApiClientService.get('/profile');
if (response.statusCode == 200) {
final user = response.data;
print('Welcome ${user['name']}!');
}
} on DioException catch (e) {
if (e.response?.statusCode == 401) {
// Token expired - auto-refresh triggered
} else if (e.type == DioExceptionType.connectionError) {
// Network error - cache fallback available
final cached = await ApiClientService.get(
'/profile',
cacheStrategy: ApiClientCacheStrategy.cacheOnly,
);
}
}
π¨ Advanced Usage
π Multi-API Configuration
Manage different API environments effortlessly:
await ApiClientPlus().initialize(
configs: [
ApiConfig(
name: 'auth',
baseUrl: 'https://auth.company.com',
requiresAuth: true,
connectTimeout: Duration(seconds: 30),
),
ApiConfig(
name: 'public',
baseUrl: 'https://api.company.com',
requiresAuth: false,
verboseLogging: false,
),
ApiConfig(
name: 'cdn',
baseUrl: 'https://cdn.company.com',
requiresAuth: false,
),
],
defaultDomain: 'auth',
);
// Switch between APIs seamlessly
final profile = await ApiClientService.get('/me', domainName: 'auth');
final posts = await ApiClientService.get('/posts', domainName: 'public');
final image = await ApiClientService.get('/avatar.png', domainName: 'cdn');
β‘ Cache Optimization
// Stale-While-Revalidate: Instant response + background refresh
final data = await ApiClientService.get(
'/dashboard',
cacheStrategy: ApiClientCacheStrategy.staleWhileRevalidate,
useCache: true,
maxStale: Duration(hours: 1),
);
// Cache-Then-Network: Progressive enhancement
final products = await ApiClientService.get(
'/products',
cacheStrategy: ApiClientCacheStrategy.cacheThenNetwork,
onCachedResponse: (cached) {
// Show cached data immediately
updateUI(cached.data);
},
);
π Authentication Flow
await ApiClientPlus().initialize(
configs: [...],
tokenGetter: () async {
// Retrieve token from secure storage
return await SecureStorage.read('auth_token');
},
onTokenInvalid: () async {
// Handle expired tokens
await SecureStorage.delete('auth_token');
Navigator.pushReplacementNamed(context, '/login');
},
);
π― Custom Headers & Options
final response = await ApiClientService.get(
'/data',
headers: {
'X-Custom-Header': 'value',
'X-Request-ID': uuid.v4(),
},
query: {
'page': 1,
'limit': 20,
'sort': 'desc',
},
timeout: Duration(seconds: 60),
);
π Performance Benchmarks
Real-World Results
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Operation β Time β Rating β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£
β API Call Overhead β ~12ms β β
Excellent β
β Route Matching β ~600ΞΌs β π Blazing Fast β
β Cache Retrieval β ~2ms β β‘ Instant β
β Plugin Initialization β ~13ms β ποΈ Quick β
β Memory Leaks β 0 growth β π‘οΈ Rock Solid β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Cache Performance Impact
// π First Request (Network)
π₯ Response Time: 450ms | Status: 200 | from_cache: false
// β‘ Second Request (Cache)
π₯ Response Time: 2ms | Status: 200 | from_cache: true
// π Result: 225x FASTER!
Load Testing
β 100 sequential calls: 1.1 seconds (11ms avg)
β 50 domain switches: 549ms (10.98ms avg)
β 1000 route matches: 627ms (0.6ms avg)
β 10 client instances: 0ms (instant)
β 20 configs setup: 1ms (blazing)
π§ Configuration Reference
ApiConfig
ApiConfig(
name: 'myapi', // Unique identifier
baseUrl: 'https://api.example.com',
connectTimeout: Duration(seconds: 30),
receiveTimeout: Duration(seconds: 30),
sendTimeout: Duration(seconds: 30),
requiresAuth: true, // Requires token
verboseLogging: false, // Detailed logs
maxRetries: 3, // Retry failed requests
defaultHeaders: { // Custom headers
'Accept': 'application/json',
'X-App-Version': '1.0.0',
},
extra: {'priority': 'high'}, // Custom metadata
)
CacheConfig
CacheConfig(
enableCache: true,
defaultTtl: Duration(minutes: 15),
priority: CachePriority.normal,
hitCacheOnNetworkFailure: true, // Fallback on error
hitCacheOnErrorCodes: [500, 502, 503, 401, 403],
)
LogConfig
LogConfig(
showLog: true,
showCacheLog: true,
logLevel: "DEBUG", // TRACE, DEBUG, INFO, WARN, ERROR
prettyJson: true,
isColored: true,
messageLimit: 300,
showTime: true,
showCaller: false,
logStyle: LogStyle.minimal, // minimal, standard, none
)
π Debugging
Enable Comprehensive Logging
await ApiClientPlus().initialize(
configs: [...],
logConfig: LogConfig(
showLog: true,
showCacheLog: true,
logLevel: "DEBUG",
prettyJson: true,
isColored: true,
),
);
Sample Log Output
INFO πΎ Cache Strategy: cache_first for /users
INFO πΎ β
CACHE HIT: /users (age: 2m 34s)
INFO π₯ Response: 2ms | 200 | from_cache: true
INFO π Cache Strategy: network_first for /posts
INFO π Making network request...
INFO π₯ Response: 156ms | 200 | from_cache: false
INFO πΎ β
Cached: /posts (ttl: 10m)
Screenshots

π€ Contributing
We welcome contributions! Here's how:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing) - Open a Pull Request
π License
This project is licensed under the MIT License - see the LICENSE file for details.
π Support & Resources
| π Documentation |
π Report Bug |
π‘ Request Feature |
β Star on GitHub |
Built with β€οΈ for the Flutter Community
pub.flutter-io.cn β’ GitHub β’ Issues
If this package helped you, consider giving it a β on GitHub!