change_emitter 0.9.4

Flutter Android iOS web

A flexible, highly composable alternative to ChangeNotifier for Flutter


import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:change_emitter/change_emitter.dart';

void main() {
    ///We'll use the Provider package to provide state.
      create: (_) => TextState(),
      child: MyApp(),

class MyApp extends StatelessWidget {
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Upstate Example')),
        body: Center(
          child: Container(
            width: 500,
            height: 700,
            child: AppBody(),

///We can bundle everything we need to display our text by extending [EmitterContainer].
///This means that when any values change, our UI updates automatically.
class TextState extends EmitterContainer {
  final textInput = TextEditingEmitter(text: 'Some text');
  final bold = ValueEmitter(false);
  final italic = ValueEmitter(false);
  final color = ValueEmitter<Color>(;
  ValueEmitter<bool> isRedAndBold;

  TextState() {
    ///This [ValueEmitter] will react to changes in [color] or [bold] and set its
    ///value using the builder. This means all we need to do is worry about setting the
    ///right color and value for bold and this will take care of itself!
    isRedAndBold = ValueEmitter.reactive(
      [color, bold],
      () => color.value == && bold.value,

  ///We have to provide a list of all [ChangeEmitter]s defined in this class.
  ///This makes for very easy disposing of resources. If [this] is ever disposed,
  ///Which happens automatically when using [ChangeEmitterProvider], all of the
  ///children will be disposed as well! Convinient!
  get children => [textInput, bold, italic, color, isRedAndBold];

  ///We actually don't want all [children] to cause our UI to update. Since [isRedAndBold] updates
  ///on changes of other elements and we don't actually need it to display our text,
  ///we override this getter to provide a subset of children that should trigger updates. We
  ///also only want our text widget to update on changes to the [textInput]'s text property.
  get emittingChildren => [textInput.text, bold, italic, color];

class AppBody extends StatelessWidget {
  Widget build(BuildContext context) {
    return Column(
      children: [
          ///[TextEditingEmitter] provides a controller for us to use. It will be disposed of automatically
          ///when our state is disposed.
          controller: Provider.of<TextState>(context, listen: false)
        Row(children: [
          Text('Bold: '),

          ///We can use a [ChangeEmitterSelector] to update some UI when only
          ///a subcomponent of our state changes. In this case we only want
          ///our switch to update when bold changes.
          ChangeEmitterSelector<TextState, ValueEmitter<bool>>(
            selector: (_, state) => state.bold,
            builder: (_, bold, __) => Switch(
              ///We get the value held by a [ValueEmitter] use the value property
              value: bold.value,

              ///We set a new value the same way.
              onChanged: (newValue) => bold.value = newValue,
        Row(children: [
          Text('Italic: '),
          ChangeEmitterSelector<TextState, ValueEmitter<bool>>(
            selector: (_, state) => state.italic,
            builder: (_, italic, __) => Switch(
              value: italic.value,
              onChanged: (value) => italic.value = value,
        Row(children: [
          Text('Color: '),
          ChangeEmitterSelector<TextState, ValueEmitter<Color>>(
            selector: (_, state) => state.color,
            builder: (_, color, __) => DropdownButton(
              items: [
                DropdownMenuItem(child: Text('red'), value:,
                DropdownMenuItem(child: Text('blue'), value:,
                DropdownMenuItem(child: Text('green'), value:,
                DropdownMenuItem(child: Text('purple'), value: Colors.purple)
              value: color.value,
              onChanged: (value) => color.value = value,
          selector: (_, TextState state) => state.isRedAndBold,
          builder: (_, isRedAndBold, __) =>
              Text("Red and bold: " + isRedAndBold.value.toString()),
          child: Text('append text'),
          onPressed: () =>
    <TextState>().textInput.text.value += ' text',
          child: Text('clear'),
          onPressed: () =><TextState>().textInput.text.value = '',

///Here is the part we care about, correctly displaying our text.
class DisplayText extends StatelessWidget {
  Widget build(BuildContext context) {
    ///We can use a vanilla [Consumer] from the Provider package which will call the builder whenever [TextState]
    return Consumer<TextState>(
      builder: (context, state, child) {
        return Text(
          style: TextStyle(
              color: state.color.value,
              fontSize: 24,
                  state.bold.value ? FontWeight.bold : FontWeight.normal,
                  state.italic.value ? FontStyle.italic : FontStyle.normal),
pub points

A flexible, highly composable alternative to ChangeNotifier for Flutter

Repository (GitHub)
View/report issues


API reference





async, flutter, provider


Packages that depend on change_emitter