leulit_flutter_actionmanager 4.2.1 copy "leulit_flutter_actionmanager: ^4.2.1" to clipboard
leulit_flutter_actionmanager: ^4.2.1 copied to clipboard

A lightweight, type-safe action dispatcher for Flutter applications. Works seamlessly across all layers - UI, domain, data, and services.

example/lib/main.dart

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

void main() {
  // Configurar logger (opcional)
  ActionManager.configureLogger(
    enabled: true,
    showTimestamp: true,
  );

  runApp(const MyApp());
}

/// Enum de acciones de ejemplo
enum AppAction {
  increment,
  decrement,
  reset,
  randomNumber,
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Action Dispatcher Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const HomePage(),
    );
  }
}

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

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  int _counter = 0;

  @override
  void initState() {
    super.initState();

    // Registrar handlers
    ActionManager.onVoid(AppAction.increment, () {
      setState(() => _counter++);
    });

    ActionManager.onVoid(AppAction.decrement, () {
      setState(() => _counter--);
    });

    ActionManager.onVoid(AppAction.reset, () {
      setState(() => _counter = 0);
    });

    ActionManager.on<int>(AppAction.randomNumber, (number) {
      if (number != null) {
        setState(() => _counter = number);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Action Dispatcher Demo'),
        actions: [
          IconButton(
            icon: const Icon(Icons.info_outline),
            onPressed: () {
              // Mostrar estadísticas
              ActionManager.printSummary();

              // También en UI
              showDialog(
                context: context,
                builder: (context) => const StatsDialog(),
              );
            },
          ),
        ],
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text('Counter Value:', style: TextStyle(fontSize: 20)),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.displayLarge,
            ),
            const SizedBox(height: 40),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                ElevatedButton.icon(
                  icon: const Icon(Icons.remove),
                  label: const Text('Decrement'),
                  onPressed: () {
                    ActionManager.dispatch(AppAction.decrement);
                  },
                ),
                const SizedBox(width: 10),
                ElevatedButton.icon(
                  icon: const Icon(Icons.add),
                  label: const Text('Increment'),
                  onPressed: () {
                    ActionManager.dispatch(AppAction.increment);
                  },
                ),
              ],
            ),
            const SizedBox(height: 20),
            ElevatedButton.icon(
              icon: const Icon(Icons.refresh),
              label: const Text('Reset'),
              onPressed: () {
                ActionManager.dispatch(AppAction.reset);
              },
            ),
            const SizedBox(height: 20),
            ElevatedButton.icon(
              icon: const Icon(Icons.shuffle),
              label: const Text('Random Number'),
              onPressed: () {
                final random = DateTime.now().millisecond;
                ActionManager.dispatch(AppAction.randomNumber, data: random);
              },
            ),
            const SizedBox(height: 40),
            const SecondWidget(),
          ],
        ),
      ),
    );
  }
}

/// Widget adicional que también escucha las mismas acciones
class SecondWidget extends StatefulWidget {
  const SecondWidget({super.key});

  @override
  State<SecondWidget> createState() => _SecondWidgetState();
}

class _SecondWidgetState extends State<SecondWidget> {
  int _localCounter = 0;

  @override
  void initState() {
    super.initState();

    // Este widget también responde a las acciones
    ActionManager.onVoid(AppAction.increment, () {
      setState(() => _localCounter++);
    });

    ActionManager.onVoid(AppAction.reset, () {
      setState(() => _localCounter = 0);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Card(
      margin: const EdgeInsets.all(16),
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          children: [
            const Text(
              'This widget also listens to actions!',
              style: TextStyle(fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 8),
            Text('Local counter: $_localCounter'),
          ],
        ),
      ),
    );
  }
}

/// Dialog que muestra estadísticas
class StatsDialog extends StatelessWidget {
  const StatsDialog({super.key});

  @override
  Widget build(BuildContext context) {
    final stats = ActionManager.getStats();

    return AlertDialog(
      title: const Text('📊 Dispatcher Stats'),
      content: Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text('Total Actions: ${stats.totalActions}'),
          Text('Total Handlers: ${stats.totalHandlers}'),
          Text('Total Dispatches: ${stats.totalDispatches}'),
          const SizedBox(height: 16),
          const Text('Action Details:',
              style: TextStyle(fontWeight: FontWeight.bold)),
          ...AppAction.values.map((action) {
            final metadata = ActionManager.getMetadata(action);
            return Padding(
              padding: const EdgeInsets.only(top: 8),
              child: Text(
                '${action.name}: ${metadata.handlerCount} handlers, '
                '${metadata.dispatchCount} dispatches',
                style: const TextStyle(fontSize: 12),
              ),
            );
          }),
        ],
      ),
      actions: [
        TextButton(
          onPressed: () => Navigator.pop(context),
          child: const Text('Close'),
        ),
      ],
    );
  }
}
0
likes
0
points
759
downloads

Publisher

unverified uploader

Weekly Downloads

A lightweight, type-safe action dispatcher for Flutter applications. Works seamlessly across all layers - UI, domain, data, and services.

Repository (GitHub)
View/report issues

Topics

#state-management #architecture #events #actions #dispatcher

License

unknown (license)

Dependencies

flutter, meta

More

Packages that depend on leulit_flutter_actionmanager