搜尋套件、儲存庫與 APP 分類

套件詳情v9.5.2

command_it

command_it 是一種基於 `ValueListenable` 和命令設計模式來管理狀態的方式。它是 flutter_command 的重新命名版本。

AndroidiOSWebmacOSWindowsLinux
近 30 天下載
5010
喜歡數
35
Pub 分數
160

安裝套件

flutter pub add command_it

套件介紹

根據套件公開資料產生的選型評估,僅供參考。

command_it 是一個基於 `ValueListenable` 和命令設計模式的狀態管理解決方案,為 Flutter 應用提供一種乾淨、反應式的處理狀態變化的途徑。最初稱為 flutter_command,它提供了一種結構化的方法來管理非同步操作和狀態更新。該套件透過將動作封裝在命令中,促進了關注點分離,使程式碼更易測試和維護。它與 Flutter 的反應式框架無縫整合,並支援所有主要平台。

適用情境

  • 管理非同步操作,如 API 呼叫
  • 處理表單提交
  • 實現撤銷/重做功能
  • 在多個小部件之間協調狀態變更
  • 建構可重用的業務邏輯層

主要特色

  • 透過 ValueListenable 實現反應式狀態
  • 命令模式用於封裝動作
  • 內建支援載入、錯誤與成功狀態
  • 與 Flutter 的 widget 樹輕鬆整合
  • 跨平台相容性

適合對象

  • 尋求輕量級狀態管理替代方案的開發者
  • 希望在使用者介面與業務邏輯之間實現清晰分離的團隊
  • 需要可預測狀態轉換的專案
  • 頻繁執行非同步操作的應用程式
  • 測試驅動開發工作流程

使用建議

  • 對於不熟悉命令模式的新使用者,可能需要一定的學習曲線
  • 不太適合非常簡單的狀態需求
  • 與更大的狀態管理解決方案相比,生態系統有限
  • 最佳搭配其他工具以實現完整的應用架構

原始 README

以下為關聯原始碼儲存庫的 README 原文快照,最新內容請造訪原始碼儲存庫。

command_it logo
Buy Me A Coffee
Sponsor

command_it codecov

📚 Complete documentation available at flutter-it.dev Check out the comprehensive docs with detailed guides, examples, and best practices!


🔄 Migration Notice (v9.0.0)

Important: Version 9.0.0 introduces new, clearer API naming. The old API is deprecated and will be removed in v10.0.0.

Quick Migration: execute() → run() | isExecuting → isRunning | canExecute → canRun

Run dart fix --apply to automatically update most usages.

Complete migration guide →


Command pattern for Flutter - wrap functions as observable objects with automatic state management

Commands replace async methods with reactive alternatives. Wrap your functions, get automatic loading states, error handling, and UI integration. No manual state tracking, no try/catch everywhere.

Call them like functions. React to their state. Simple as that.

Part of flutter_it — A construction set of independent packages. command_it works standalone or combines with watch_it for reactive UI updates.

Why Commands?

  • 🎯 Declarative — Wrap functions, get observable execution state automatically
  • ⚡ Automatic State — isRunning, value, errors tracked without manual code
  • 🛡️ Smart Error Handling — Route errors globally/locally with filters
  • 🔒 Built-in Protection — Prevents parallel execution automatically
  • 🎛️ Restrictions — Disable commands conditionally (auth, network, etc.)
  • 🧪 Testable — Easier to test than traditional async methods

Learn more about the benefits →

Quick Start

Installation

Add to your pubspec.yaml:

dependencies:
  command_it: ^9.0.2
  listen_it: ^5.3.3  # Required - commands build on ValueListenable
Basic Example
import 'package:command_it/command_it.dart';

// 1. Create a command that wraps your async function
class CounterManager {
  int _counter = 0;

  late final incrementCommand = Command.createAsyncNoParam<String>(
    () async {
      await Future.delayed(Duration(milliseconds: 500));
      _counter++;
      return _counter.toString();
    },
    initialValue: '0',
  );
}

// 2. Use it in your UI - command is a ValueListenable
class CounterWidget extends StatelessWidget {
  final manager = CounterManager();

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        // Shows loading indicator automatically while command runs
        ValueListenableBuilder<bool>(
          valueListenable: manager.incrementCommand.isRunning,
          builder: (context, isRunning, _) {
            if (isRunning) return CircularProgressIndicator();

            return ValueListenableBuilder<String>(
              valueListenable: manager.incrementCommand,
              builder: (context, value, _) => Text('Count: $value'),
            );
          },
        ),
        ElevatedButton(
          onPressed: manager.incrementCommand.run,
          child: Text('Increment'),
        ),
      ],
    );
  }
}

That's it! The command automatically:

  • Prevents parallel execution
  • Tracks isRunning state
  • Publishes results
  • Handles errors

Full tutorial

Using CommandBuilder

Simplify your UI code with the built-in builder widget:

CommandBuilder<void, String>(
  command: manager.incrementCommand,
  whileRunning: (context, _, __) => CircularProgressIndicator(),
  onData: (context, value, _) => Text('Count: $value'),
  onError: (context, error, _, __) => Text('Error: $error'),
)

Key Features

Command Types

Create commands for any function signature:

Command Properties

Observe different aspects of execution:

  • value — Last successful result
  • isRunning — Async execution state
  • isRunningSync — Synchronous version for restrictions
  • canRun — Combined restriction and running state
  • errors — Stream of errors
  • results — CommandResult with all data at once
Error Handling

Declarative error routing with filters:

Advanced Features
Piping Commands

Chain commands together with the pipeToCommand() extension. When the source completes successfully, it automatically triggers the target command:

// Trigger refresh after save completes
saveCommand.pipeToCommand(refreshCommand);

// Transform result before passing to target
userIdCommand.pipeToCommand(fetchUserCommand, transform: (id) => UserRequest(id));

// Pipe from any ValueListenable - track execution state changes
longRunningCommand.isRunning.pipeToCommand(spinnerStateCommand);

The pipeToCommand() extension works on any ValueListenable, including commands, isRunning, results, or plain ValueNotifier. Returns a ListenableSubscription for manual cancellation if needed.

⚠️ Warning: Circular pipes (A→B→A) cause infinite loops. Ensure your pipe graph is acyclic.

Ecosystem Integration

Built on listen_it — Commands are ValueListenable objects, so they work with all listen_it operators (map, debounce, where, etc.).

// Register with get_it
di.registerLazySingleton(() => TodoManager());

// Use commands in your managers
class TodoManager {
  final loadTodosCommand = Command.createAsyncNoParam<List<Todo>>(
    () => api.fetchTodos(),
    [],
  );

  // Debounce search with listen_it operators
  final searchCommand = Command.createSync<String, String>((s) => s, '');

  TodoManager() {
    searchCommand.debounce(Duration(milliseconds: 500)).listen((term, _) {
      loadTodosCommand.run();
    });
  }
}

Want more? Combine with other flutter_it packages:

  • listen_it — Required dependency. ValueListenable operators and reactive collections.

  • Optional: watch_it — State management. Watch commands reactively without builders: watchValue((m) => m.loadCommand).

  • Optional: get_it — Service locator for dependency injection. Access managers with commands from anywhere: di<TodoManager>().

💡 flutter_it is a construction set — command_it works standalone. Add watch_it and get_it when you need reactive UI and dependency injection.

Explore the ecosystem →

AI-Assisted Development

This package ships an Agent Skill for AI coding assistants (Claude Code, Cursor, GitHub Copilot, Codex, Gemini CLI and others) in skills/command-it-expert/. It teaches them the critical rules, common patterns and anti-patterns of command_it. Install it into your project with the official Dart skills tool:

dart run skills@ get

For the ecosystem-wide skills (architecture guidance, feed/data-source patterns, overview) and the skills of the other flutter_it packages run:

dart run skills@ add flutter-it/flutter_it

Learn more about AI skills →

Learn More

📖 Documentation
💬 Community & Support

Contributing

Contributions are welcome! Please read the contributing guidelines before submitting PRs.

License

MIT License - see LICENSE file for details.


Part of the flutter_it ecosystem — Build reactive Flutter apps the easy way. No codegen, no boilerplate, just code.

所屬分類

依賴

依賴清單 3 項

原始碼儲存庫

使用此套件的專案