Tipos de Command
Aprende sobre el patrón de funciones factory de command_it para crear commands. Entender este patrón hace fácil elegir la factory correcta para tus necesidades.
¿Por Qué Funciones Factory?
Los Commands usan funciones factory estáticas en lugar de un solo constructor porque:
Seguridad de tipos - Cada factory acepta exactamente la firma de función correcta:
createAsync<String, List<Todo>>tomaFuture<List<Todo>> Function(String)createAsyncNoParam<List<Todo>>tomaFuture<List<Todo>> Function()- Sin riesgo de pasar el tipo de función incorrecto
Simplicidad de implementación - Diferentes firmas de función (0-2 parámetros, retornos void/no-void) requerirían múltiples parámetros de función opcionales en un constructor, haciéndolo propenso a errores y confuso
Intención clara - El nombre de la factory te dice exactamente qué estás creando:
createAsyncNoParam<List<Todo>>es más claro queCommand<void, List<Todo>>()
El Patrón de Nomenclatura
Las 12 funciones factory siguen una fórmula simple:
create + [Sync|Async|Undoable] + [NoParam] + [NoResult]Cómo leer los nombres:
- Sync/Async/Undoable - Qué tipo de command (siempre presente)
- NoParam - Si está presente, el command NO toma parámetros
- NoResult - Si está presente, el command retorna void
- Partes omitidas - Si "NoParam" o "NoResult" falta, esa característica ESTÁ presente
Ejemplos:
| Nombre de Factory | ¿Tiene Parámetro? | ¿Tiene Resultado? | Tipo |
|---|---|---|---|
createAsync<TParam, TResult> | ✅ Sí (TParam) | ✅ Sí (TResult) | Async |
createAsyncNoParam<TResult> | ❌ No (void) | ✅ Sí (TResult) | Async |
createAsyncNoResult<TParam> | ✅ Sí (TParam) | ❌ No (void) | Async |
createSyncNoParamNoResult | ❌ No (void) | ❌ No (void) | Sync |
createUndoable<TParam, TResult, TUndoState> | ✅ Sí (TParam) | ✅ Sí (TResult) | Undoable |
Idea clave: Si "NoParam" o "NoResult" aparece en el nombre, esa característica está AUSENTE. Si se omite, está PRESENTE.
Los Commands NoResult Aún Notifican a los Listeners
Aunque los commands NoResult retornan void, aún notifican a los listeners cuando completan exitosamente. Esto significa que puedes observarlos para disparar actualizaciones de UI, navegación u otros efectos secundarios.
final saveCommand = Command.createAsyncNoResult<Data>(
(data) async => await api.save(data),
);
// Aún puedes escuchar la completación
saveCommand.listen((_, __) {
showSnackbar('¡Guardado exitosamente!');
});
// O usar con watch_it
watchValue(saveCommand, (_, __) {
// Se llama cuando save completa
});Los Commands son ValueListenable<TResult> donde TResult es void para variantes NoResult - el valor no cambia, pero las notificaciones aún se disparan en la ejecución.
Referencia de Parámetros
Aquí está la firma completa de createAsync<TParam, TResult> - la función factory más común. Todas las otras factories comparten estos mismos parámetros (o un subconjunto):
static Command<TParam, TResult> createAsync<TParam, TResult>(
Future<TResult> Function(TParam x) func, {
required TResult initialValue,
ValueListenable<bool>? restriction,
RunInsteadHandler<TParam>? ifRestrictedRunInstead,
bool includeLastResultInCommandResults = false,
ErrorFilter? errorFilter,
ErrorFilterFn? errorFilterFn,
bool notifyOnlyWhenValueChanges = false,
String? debugName,
})Parámetros requeridos:
func- La función async a envolver (parámetro posicional). Toma un parámetro de tipoTParamy retornaFuture<TResult>initialValue- El valor inicial del command antes de la primera ejecución (parámetro nombrado requerido). Los Commands sonValueListenable<TResult>y necesitan un valor inmediatamente. No disponible para commands void (ver variantes NoResult abajo)
Parámetros opcionales:
restriction-ValueListenable<bool>para habilitar/deshabilitar el command dinámicamente. Cuando estrue, el command no puede ejecutarse. Ver RestriccionesifRestrictedRunInstead- Función alternativa llamada cuando el command está restringido (ej., mostrar diálogo de login). Ver RestriccionesincludeLastResultInCommandResults- Cuando estrue, mantiene el último valor exitoso visible enCommandResult.datadurante estados de ejecución y error. Por defecto esfalse. Ver Command Results - includeLastResultInCommandResults para explicación detallada y casos de usoerrorFilter/errorFilterFn- Configura cómo se manejan los errores (handler local, handler global, o ambos). Ver Manejo de ErroresnotifyOnlyWhenValueChanges- Cuando estrue, solo notifica a listeners si el valor realmente cambia. Por defecto notifica en cada ejecucióndebugName- Identificador para logging y debugging, incluido en mensajes de error
Diferencias de Variantes
Las 12 funciones factory usan el mismo patrón de parámetros de arriba, con estas variaciones:
Sync vs Async:
- Commands Sync (
createSync*):- Parámetro de función:
TResult Function(TParam)(función regular) - Ejecutan inmediatamente
- Sin soporte de
isRunning(accederlo lanza una excepción)
- Parámetro de función:
- Commands Async (
createAsync*):- Parámetro de función:
Future<TResult> Function(TParam)(retorna Future) - Proporcionan tracking de
isRunningdurante la ejecución
- Parámetro de función:
Variantes NoParam:
- La firma de función no tiene parámetro:
Future<TResult> Function()en lugar deFuture<TResult> Function(TParam) ifRestrictedRunInsteadno tiene parámetro:void Function()en lugar deRunInsteadHandler<TParam>
Variantes NoResult:
- La función retorna
void:Future<void> Function(TParam)en lugar deFuture<TResult> Function(TParam) - Sin parámetro
initialValue(commands void no necesitan valor inicial) - Sin parámetro
includeLastResultInCommandResults(nada que incluir)
Commands Undoable:
- Cubiertos en detalle en la sección de Commands Undoable abajo
Commands Undoable
Los commands undoable extienden commands async con capacidad de deshacer. Mantienen un UndoStack<TUndoState> que almacena snapshots de estado, permitiéndote deshacer operaciones.
Firma completa:
static Command<TParam, TResult> createUndoable<TParam, TResult, TUndoState>(
Future<TResult> Function(TParam, UndoStack<TUndoState>) func, {
required TResult initialValue,
required UndoFn<TUndoState, TResult> undo,
bool undoOnExecutionFailure = true,
ValueListenable<bool>? restriction,
RunInsteadHandler<TParam>? ifRestrictedRunInstead,
bool includeLastResultInCommandResults = false,
ErrorFilter? errorFilter,
ErrorFilterFn? errorFilterFn,
bool notifyOnlyWhenValueChanges = false,
String? debugName,
})Parámetros requeridos:
func- Tu función async que recibe DOS parámetros: el parámetro del command (TParam) Y el undo stack (UndoStack<TUndoState>) donde haces push de snapshots de estado (parámetro posicional)initialValue- El valor inicial del command antes de la primera ejecución (parámetro nombrado requerido)undo- Función handler llamada para realizar la operación de deshacer (parámetro nombrado requerido):darttypedef UndoFn<TUndoState, TResult> = FutureOr<TResult> Function( UndoStack<TUndoState> undoStack, Object? reason )Haz pop del estado del stack y restáuralo. Se llama cuando el usuario manualmente deshace o cuando
undoOnExecutionFailure: truey la ejecución falla
Parámetros opcionales:
undoOnExecutionFailure- Cuando estrue(por defecto), automáticamente llama al handler de undo y restaura el estado si el command falla. Perfecto para actualizaciones optimistas que necesitan rollback en error
Parámetros de tipo:
TParam- Tipo de parámetro del command (igual que commands regulares)TResult- Tipo de valor de retorno (igual que commands regulares)TUndoState- Tipo de snapshot de estado necesario para deshacer la operación
Parámetros heredados:
Todos los otros parámetros (initialValue, restriction, errorFilter, etc.) funcionan igual que en createAsync - ver la sección Referencia de Parámetros arriba.
Métodos adicionales:
undo()- Manualmente deshace la última operación llamando al handler de undo. El handler de undo recibe elUndoStacky puede hacer pop del estado para restaurar valores previos
Ver también:
- Mejores Prácticas - Commands Undoable para ejemplos prácticos
- Manejo de Errores - Auto-Undo en Fallo para patrones de recuperación de errores
Ver También
- Fundamentos de Command - Ejemplos de uso detallados y patrones
- Propiedades del Command - Entendiendo el estado del command (value, isRunning, canRun, errors)
- Mejores Prácticas - Cuándo usar qué factory y patrones de producción
- Manejo de Errores - Estrategias de gestión de errores
- Restricciones - Patrones dinámicos de habilitar/deshabilitar commands