change_emitter 0.9.3

Flutter Android iOS web

A flexible, highly composable alternative to ChangeNotifier for Flutter

change_emitter #

ChangeEmitter is a highly composable, flexible alternative to ChangeNotifier in the Flutter framework that can be used with Provider for state management. Instead of maintaining a list of callbacks, ChangeEmitters use a stream of change objects which can contain specific information about changes and are easier to manipulate. Comes with a handful of basic ChangeEmitters that you can combine to create your own state abstractions.

Installation #

To use ChangeEmitter, add it to your dependencies in your pubspec.yaml file as well as the provider package:

dependencies:
  provider:
  change_emitter:

Usage #

To get started quickly check out the example.

And the API documentation

Built in ChangeEmitters #

Comes with ChangeEmitters for basic primitives and way to compose them.

ValueEmitter:

//ValueEmitters hold simple values
var toggle = ValueEmitter(true);

//All ChangeEmitters expose a stream of changes
var subscription = boolToggle.changes.listen((change)=>print('toggle switched'));

//set a new value
toggle.value = false; //prints 'toggle switched'

//read the current value
print('current value: ' + toggle.value.toString()); // prints 'current value: false'

//Cancel the stream subscription
subscription.cancel();

//ChangeEmitters need to be disposed when they're no longer needed.
toggle.dispose(); 

ListEmitter:

//Holds a list of elements  
var intList = ListEmitter([1,3,5]);  

intList.addAll([2,8,10]);
intList.retainWhere((element)=>element%2==0);  
  
var subscription = intList.notifications.listen((notif)=>print('changed'));

//ListEmitter will only emit changes when you call emit but will
//only do so if there has actually been a change.
//This allows you to perform multiple changes to the list before updating your UI
intList.emit();  //prints 'changed'
intList.emit();  //does nothing
subscription.cance();
intList.dispose();  

MapEmitter:

//A map implementation
var colorMap = MapEmitter<String,Color>({});  

colorMap['red']=Colors.red;  
colorMap.emit();  
  
colorMap.dispose();

EmitterContainer:

//EmitterContainer allows you to compose multiple ChangeEmitters into a single unit
//which is also a ChangeEmitter 

class TextState extends EmitterContainer {
  final text = ValueEmitter('Some text');  
  final bold = ValueEmitter(false);  
  final italic = ValueEmitter(false);  
  final color = ValueEmitter<Color>(Colors.red);  
    
  //Override this getter with list of all ChangeEmitters defined in this class.  
  //This has two functions. First, all of the elements will be disposed  
  //when this class is disposed (convenient!). Second, this class 
  //will also emit a change whenever a child changes.  
  @override  
  get children => [text, bold, italic, color];  
  
  //If you just want a subset of children to notify listeners you can optionally override this getter.   
  //@override  
  //get emittingChildren => [text, bold];  
}  
  
var myTextState = TextState();  
  
var subscription = myTextState.changes.listen((notif)=>'changed!');  
  
myTestState.italic.value = true;  //prints 'changed!'
  
//We can notify listeners without changing any children:  
myTextState.emit(); //prints 'changed!' 
  
//We can also change one of the children's values without causing the container to emit a change.
//The child will still emit a change however:  
myTextState.bold.quietSet(true); //nothing printed to the console  
  
//You can do this for ListEmitter/Map/Containers as well
//someListEmitter.emit(quiet: true);
  
//dispose of resources. 
subscription.cancel();
myTextState.dispose();

Providing and Consuming State #

ChangeEmitter uses the Provider package along with some extra classes to provide and consume state.

//Povide your state to a part of the widget tree
//This will automatically dispose your state when removed from the widget tree

runApp(  
  ChangeEmitterProvider(  
    create: (_) => TextState(),  
    child: MyApp(),  
  )  
);  
  
class MyApp extends StatelessWidget{

  @override
  build(){
    //You can use Provider as you would expect to get and depend on your state
    //var textState = Provider.of<TextState>(context);

    return Column(
      children:[
        //You can update your UI based on just a part of your state using a selector  
        ChangeEmitterSelector<TextState,ValueEmitter<bool>>(  
          selector: (_, state) => state.bold  
          builder: (_, bold, __){  
            return Switch(  
              value: bold.value,  
              onChange: (newValue) => bold.value = newValue  
            )  
          }  
        ),  
        //Use a vanilla Consumer to update on any change to your state  
        Consumer<TextState>(  
          builder: (_, state, __){  
            return Text(  
              state.text.value,  
              style: TextStyle(  
                color: state.color.value,
                fontWeight:  
                  state.bold.value ? FontWeight.bold : FontWeight.normal,  
                fontStyle:  
                  state.italic.value ? FontStyle.italic : FontStyle.normal),  
              );  
          }  
        )  
      ]  
    );  
  }  
}  
0
likes
110
pub points
9%
popularity

A flexible, highly composable alternative to ChangeNotifier for Flutter

Repository (GitHub)
View/report issues

Documentation

API reference

Uploader

jonathan.aird@gmail.com

License

MIT (LICENSE)

Dependencies

async, flutter, provider

More

Packages that depend on change_emitter