flutter_resilience 1.0.0 copy "flutter_resilience: ^1.0.0" to clipboard
flutter_resilience: ^1.0.0 copied to clipboard

A production-ready Flutter/Dart package for network resilience. Implements automatic API retry, exponential backoff, circuit breaker, timeout handling, and request fallback logic. Inspired by Polly, d [...]

example/main.dart

import 'package:flutter/material.dart';
import 'package:flutter_resilience/flutter_resilience.dart';
import 'dart:async';

void main() {
  runApp(const ResilienceExampleApp());
}

class ResilienceExampleApp extends StatelessWidget {
  const ResilienceExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Resilience Demo',
      theme: ThemeData(
        useMaterial3: true,
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        brightness: Brightness.dark,
      ),
      home: const ResilienceHomePage(),
    );
  }
}

class ResilienceHomePage extends StatefulWidget {
  const ResilienceHomePage({super.key});

  @override
  State<ResilienceHomePage> createState() => _ResilienceHomePageState();
}

class _ResilienceHomePageState extends State<ResilienceHomePage> {
  final List<String> _logs = [];
  bool _isLoading = false;
  late ResilientClient _client;
  late CircuitBreaker _circuitBreaker;

  @override
  void initState() {
    super.initState();
    _circuitBreaker = CircuitBreaker(
      failureThreshold: 3,
      resetTimeout: const Duration(seconds: 5),
      onStateChanged: (state) =>
          _addLog('Circuit State: ${state.name.toUpperCase()}'),
    );

    _client = ResilientClient(
      retries: 3,
      strategy: RetryStrategy.exponential,
      retryDelay: const Duration(seconds: 1),
      circuitBreaker: _circuitBreaker,
      timeout: const Duration(seconds: 2),
      retryIf: (error) => error is Exception,
    );
  }

  void _addLog(String message) {
    setState(() {
      _logs.insert(0,
          '${DateTime.now().toIso8601String().split('T').last.substring(0, 8)}: $message');
    });
  }

  Future<void> _simulateRequest(bool shouldFail) async {
    setState(() => _isLoading = true);
    _addLog('Executing Request (Should Fail: $shouldFail)...');

    try {
      final result = await _client.execute(
        () async {
          _addLog('Attempting request...');
          await Future<void>.delayed(const Duration(milliseconds: 500));
          if (shouldFail) {
            throw Exception('Simulated API Failure');
          }
          return 'Success Data from API';
        },
        fallback: () => 'Fallback Data (Offline Cache)',
      );
      _addLog('RESULT: $result');
    } catch (e) {
      _addLog('ERROR: $e');
    } finally {
      setState(() => _isLoading = false);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter Resilience Demo'),
        actions: [
          IconButton(
            onPressed: () {
              setState(_logs.clear);
              _circuitBreaker.reset();
            },
            icon: const Icon(Icons.refresh),
          ),
        ],
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            const _InfoCard(),
            const SizedBox(height: 16),
            Row(
              children: [
                Expanded(
                  child: ElevatedButton.icon(
                    onPressed:
                        _isLoading ? null : () => _simulateRequest(false),
                    icon: const Icon(Icons.check_circle),
                    label: const Text('Success Request'),
                    style: ElevatedButton.styleFrom(
                      backgroundColor: Colors.green.withAlpha(51),
                    ),
                  ),
                ),
                const SizedBox(width: 8),
                Expanded(
                  child: ElevatedButton.icon(
                    onPressed: _isLoading ? null : () => _simulateRequest(true),
                    icon: const Icon(Icons.error),
                    label: const Text('Failing Request'),
                    style: ElevatedButton.styleFrom(
                      backgroundColor: Colors.red.withAlpha(51),
                    ),
                  ),
                ),
              ],
            ),
            const SizedBox(height: 16),
            const Text('Logs',
                style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18)),
            const SizedBox(height: 8),
            Expanded(
              child: Container(
                decoration: BoxDecoration(
                  color: Colors.black26,
                  borderRadius: BorderRadius.circular(8),
                  border: Border.all(color: Colors.white10),
                ),
                child: ListView.separated(
                  padding: const EdgeInsets.all(8),
                  itemCount: _logs.length,
                  separatorBuilder: (_, __) =>
                      const Divider(height: 1, color: Colors.white10),
                  itemBuilder: (context, index) {
                    final log = _logs[index];
                    return Padding(
                      padding: const EdgeInsets.symmetric(vertical: 4),
                      child: Text(
                        log,
                        style: TextStyle(
                          fontFamily: 'Courier',
                          color: log.contains('ERROR')
                              ? Colors.redAccent
                              : (log.contains('Success')
                                  ? Colors.greenAccent
                                  : Colors.white70),
                        ),
                      ),
                    );
                  },
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class _InfoCard extends StatelessWidget {
  const _InfoCard();

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Text(
              'Configuration:',
              style: TextStyle(fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 4),
            const Text('• Retries: 3 with Exponential Backoff'),
            const Text('• Timeout: 2 seconds'),
            const Text('• Circuit Breaker Threshold: 3 failures'),
            const Text('• Reset Timeout: 5 seconds'),
            const SizedBox(height: 8),
            Text(
              'Watch the logs to see retry attempts and circuit state transitions.',
              style: TextStyle(
                  color: Theme.of(context).colorScheme.primary,
                  fontStyle: FontStyle.italic),
            ),
          ],
        ),
      ),
    );
  }
}
1
likes
0
points
181
downloads

Publisher

unverified uploader

Weekly Downloads

A production-ready Flutter/Dart package for network resilience. Implements automatic API retry, exponential backoff, circuit breaker, timeout handling, and request fallback logic. Inspired by Polly, designed specifically for Flutter and Dart network stability.

Homepage
Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

async, flutter, http

More

Packages that depend on flutter_resilience