api_client_plus 1.0.2
api_client_plus: ^1.0.2 copied to clipboard
A powerful Flutter plugin for managing multiple API endpoints with dynamic routing, caching, authentication, and performance-optimized HTTP calls.
ð 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 Friendly #Clean API design |
ðĒ Production Ready #Extensive 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': '[email protected]'},
);
// 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 |