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

outdated

Reactive event handler wrapper class inspired by ReactiveUI.

RxCommand #

RxCommand is an Reactive Extensions (Rx) based abstraction for event handlers. It is based on ReactiveCommand for the ReactiveUI framework. It makes heavy use of the RxDart package.

PRs are always welcome ;-)

If you don't know Rx think of it as Dart Streams on steroids. RxCommand capsules a given handler function that can then be executed by its execute method. The result of this method is then published through its results Observable (Observable wrap Dart Streams). Additionally it offers Observables for it's current execution state, if the command can be executed and for all possibly thrown exceptions during command execution.

A very simple example

final command = RxCommand.createSync3<int, String>((myInt) => "$myInt");

command.results.listen((s) => print(s)); // Setup the listener that now waits for events, not doing anything

// Somwhere else
command.execute(10); // the listener will print "10"

Getting Started #

Add to your pubspec.yaml dependencies to rxdartand rx_command. (As long as the package is not published to Dart Packages please see the dependency entry of the sample App)

An RxCommand is a generic class of type RxCommand<TParam, TRESULT> where TPARAM is the type of data that is passed when calling execute and TResult denotes the return type of the handler function. To signal that a handler doesn't take a parameter or returns a value use the dummy type Unit

An example of the declaration from the included sample App

RxCommand<String,List<WeatherEntry>>  updateWeatherCommand;
RxCommand<bool,bool>  switchChangedCommand;

updateWeatherCommand expects a handler that takes a String as parameter and returns a List<WeatherEntry>. switchChangedCommand expects and returns a bool value

Creating RxCommands #

For the different variations of possible handler methods RxCommand offers several factory methods for synchronous and asynchronous handlers. Due to the limitation that Dart doesn't allow method overloading they are numbered and look like this.

  /// Creates  a RxCommand for a synchronous handler function with no parameter and no return type 
  /// `action`: handler function
  /// `canExecute` : observable that can bve used to enable/diable the command based on some other state change
  /// if omitted the command can be executed always except it's already executing
  static RxCommand<Unit, Unit> createSync(Action action,[Observable<bool> canExecute])

The sample App contains a Switch widget that enables/disables the update command. The switch itself is bound to the switchChangedCommand that's result is then used as canExcecute of the updateWeatherCommand:

switchChangedCommand = RxCommand.createSync3<bool,bool>((b)=>b);

// We pass the result of switchChangedCommand as canExecute Observable to the upDateWeatherCommand
updateWeatherCommand = RxCommand.createAsync3<String,List<WeatherEntry>>(update,switchChangedCommand.results);

As the Update Button's building is based on a StreamBuilderthat listens on the canExecute Observable of the updateWeatherCommand the buttons enabled/disabled state gets automatically updated when the Switch's state changes

Using RxCommands #

RxCommand is typically used in a ViewModel of a Page, which is made accessible to the Widgets via an InheritedWidget. Its executemethod can then directly be assigned as event handler of the Widgets.

The result of the command is best used with a StreamBuilder or inside a StatefulWidget.

By subscribing (listening) to the isExecuting property of a RxCommand you can react on any execution state change of the command. E.g. show a spinner while the command is running.

By subscribing to the canExecute property of a RxCommand you can react on any state change of the executability of the command.

Disposing subscriptions (listeners) #

When subscribing to an Observable with .listen you should store the returned StreamSubscription and call .cancel on it if you want to cancel this subscription to a later point or if the object where the subscription is made is getting destroyed to avoid memory leaks. RxCommand has a dispose function that will cancel all active subscriptions on its observables. Calling disposebefore a command gets out of scope is a good practise.

Exploring the sample App #

The best way to understand how RxCommand is used is to look at the supplied sample app which is a simple app that queries a REST API for weather data.

The ViewModel #

It follow the MVVM design pattern so all business logic is bundled in the WeatherViewModel class in weather_viewmodel.dart.

It is made accessible to the Widgets by using an InheritedWidget which is defined in main.dart and returns and instance of WeatherViewModelwhen used like TheViewModel.of(context)

The view model publishes two commands

  • updateWeatherCommand which makes a call to the weather API and filters the result based on a string that is passed to execute. Its result will be bound to a StreamBuilderin your View.
  • switchChangedCommand which will be bound to a Switch widget to enable/disable the `updateWeatherCommand.

The View #

main.dart creates the ViewModel and places it at the very base of the app`s widget tree.

homepage.dart creates a Column with a

  • TextField where you can enter a filter text which binds to the view models onFilterEntryChanged handler.

  • a middle block which can either be a ListView (WeatherListView) or a busy spinner. It is created by a StreamBuilder which listens to
    TheViewModel.of(context).updateWeatherCommand.isExecuting

  • A row with the Update Button and a Switch that toggles if an update should be possible or not by calling TheViewModel.of(context).switchChangedCommand.execute). To change the enabled state of the button the button is build by a StreamBuilder that listens to the TheViewModel.of(context).updateWeatherCommand.canExecute

listview.dart implements WeatherListView which consists again of a StreamBuilder which updates automatically by listening on TheViewModel.of(context).updateWeatherCommand.results

45
likes
0
pub points
84%
popularity

Publisher

verified publisherfluttercommunity.dev

Reactive event handler wrapper class inspired by ReactiveUI.

Repository (GitHub)
View/report issues

License

unknown (LICENSE)

Dependencies

flutter, rxdart

More

Packages that depend on rx_command