result_utils 0.0.1 copy "result_utils: ^0.0.1" to clipboard
result_utils: ^0.0.1 copied to clipboard

A Flutter package providing a Result pattern for error handling using sealed classes (Success/Error).

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:result_utils/result_utils.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Result Utils Example',
      theme: ThemeData(useMaterial3: true, colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple)),
      home: const ExamplePage(),
    );
  }
}

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

  @override
  State<ExamplePage> createState() => _ExamplePageState();
}

class _ExamplePageState extends State<ExamplePage> {
  final TextEditingController _dividendController = TextEditingController();
  final TextEditingController _divisorController = TextEditingController();
  String _result = 'Enter two numbers to divide';

  /// Example 1: Simple sync function returning FutureResult
  FutureResult<int> divide(int a, int b) {
    if (b == 0) {
      return FutureResult.error('Cannot divide by zero');
    }
    return FutureResult.success(a ~/ b);
  }

  /// Example 2: Async function wrapped with futureToResult
  Future<FutureResult<String>> fetchUserData(String userId) async {
    return futureToResult(
      Future.delayed(const Duration(seconds: 1), () {
        if (userId.isEmpty) {
          throw Exception('User ID cannot be empty');
        }
        return 'User $userId loaded successfully!';
      }),
    );
  }

  void _handleDivision() {
    final dividend = int.tryParse(_dividendController.text);
    final divisor = int.tryParse(_divisorController.text);

    if (dividend == null || divisor == null) {
      setState(() {
        _result = 'Error: Please enter valid numbers';
      });
      return;
    }

    final result = divide(dividend, divisor);

    setState(() {
      if (result.hasError) {
        _result = 'Error: ${result.error}';
      } else {
        _result = '$dividend ÷ $divisor = ${result.value}';
      }
    });
  }

  Future<void> _handleAsyncFetch() async {
    setState(() {
      _result = 'Loading...';
    });

    final result = await fetchUserData('user123');

    setState(() {
      if (result.hasError) {
        _result = 'Error: ${result.error}';
      } else {
        _result = result.value ?? 'Unknown result';
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Result Utils Example')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: SingleChildScrollView(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              // Example 1: Sync Result Pattern
              const Text(
                'Example 1: Simple Division (Sync)',
                style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
              ),
              const SizedBox(height: 16),
              TextField(
                controller: _dividendController,
                decoration: const InputDecoration(labelText: 'Dividend', border: OutlineInputBorder()),
                keyboardType: TextInputType.number,
              ),
              const SizedBox(height: 12),
              TextField(
                controller: _divisorController,
                decoration: const InputDecoration(labelText: 'Divisor', border: OutlineInputBorder()),
                keyboardType: TextInputType.number,
              ),
              const SizedBox(height: 16),
              ElevatedButton(onPressed: _handleDivision, child: const Text('Divide')),
              const SizedBox(height: 20),
              Container(
                padding: const EdgeInsets.all(12),
                decoration: BoxDecoration(
                  border: Border.all(color: Colors.grey),
                  borderRadius: BorderRadius.circular(8),
                ),
                child: Text(_result, style: const TextStyle(fontSize: 16)),
              ),
              const SizedBox(height: 32),
              // Example 2: Async Result Pattern
              const Text(
                'Example 2: Async Operation (with futureToResult)',
                style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
              ),
              const SizedBox(height: 16),
              ElevatedButton(onPressed: _handleAsyncFetch, child: const Text('Fetch User Data')),
              const SizedBox(height: 20),
              Container(
                padding: const EdgeInsets.all(12),
                decoration: BoxDecoration(
                  border: Border.all(color: Colors.grey),
                  borderRadius: BorderRadius.circular(8),
                ),
                child: Text(_result, style: const TextStyle(fontSize: 16)),
              ),
              const SizedBox(height: 32),
              // Info Box
              Container(
                padding: const EdgeInsets.all(12),
                decoration: BoxDecoration(
                  color: Colors.blue.shade50,
                  borderRadius: BorderRadius.circular(8),
                  border: Border.all(color: Colors.blue),
                ),
                child: const Text(
                  'The Result pattern replaces try-catch with type-safe Success/Error handling. '
                  'No exceptions are thrown; instead, functions return FutureResult<T> that is '
                  'either Success or Error. This makes error handling explicit and compile-time safe.',
                  style: TextStyle(fontSize: 14),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    _dividendController.dispose();
    _divisorController.dispose();
    super.dispose();
  }
}
0
likes
160
points
55
downloads

Documentation

API reference

Publisher

verified publishernessoftware.com

Weekly Downloads

A Flutter package providing a Result pattern for error handling using sealed classes (Success/Error).

Repository (GitHub)
View/report issues

Topics

#error-handling #result-pattern #sealed-classes #exception-handling

License

MIT (license)

Dependencies

flutter

More

Packages that depend on result_utils