A Widget that passes a Reactive Model to all of it's children

Related tags

Templates dart flutter
Overview

scoped_model

Build Status codecov

A set of utilities that allow you to easily pass a data Model from a parent Widget down to its descendants. In addition, it also rebuilds all of the children that use the model when the model is updated. This library was originally extracted from the Fuchsia codebase.

This Library provides three main classes:

  • The Model class. You will extend this class to create your own Models, such as SearchModel or UserModel. You can listen to Models for changes!
  • The ScopedModel Widget. If you need to pass a Model deep down your Widget hierarchy, you can wrap your Model in a ScopedModel Widget. This will make the Model available to all descendant Widgets.
  • The ScopedModelDescendant Widget. Use this Widget to find the appropriate ScopedModel in the Widget tree. It will automatically rebuild whenever the Model notifies that change has taken place.

This library is built upon several features of Flutter:

  • The Model class implements the Listenable interface
    • AnimationController and TextEditingController are also Listenables
  • The Model is passed down the Widget tree using an InheritedWidget. When an InheritedWidget is rebuilt, it will surgically rebuild all of the Widgets that depend on its data. No need to manage subscriptions!
  • It uses the AnimatedBuilder Widget under the hood to listen to the Model and rebuild the InheritedWidget when the model changes.

Examples

  • Counter App - Introduction to the tools provided by Scoped Model.
  • Todo App - Shows how to write a Todo app with persistence and tests.

Usage

Let's demo the basic usage with the all-time favorite: A counter example!

// Start by creating a class that holds some view the app's state. In
// our example, we'll have a simple counter that starts at 0 can be 
// incremented.
//
// Note: It must extend from Model.  
class CounterModel extends Model {
  int _counter = 0;

  int get counter => _counter;

  void increment() {
    // First, increment the counter
    _counter++;
    
    // Then notify all the listeners.
    notifyListeners();
  }
}

// Create our App, which will provide the `CounterModel` to 
// all children that require it! 
class CounterApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // First, create a `ScopedModel` widget. This will provide 
    // the `model` to the children that request it. 
    return new ScopedModel<CounterModel>(
      model: new CounterModel(),
      child: new Column(children: [
        // Create a ScopedModelDescendant. This widget will get the
        // CounterModel from the nearest ScopedModel<CounterModel>. 
        // It will hand that model to our builder method, and rebuild 
        // any time the CounterModel changes (i.e. after we 
        // `notifyListeners` in the Model). 
        new ScopedModelDescendant<CounterModel>(
          builder: (context, child, model) => new Text('${model.counter}'),
        ),
        new Text("Another widget that doesn't depend on the CounterModel")
      ])
    );
  }
}

Finding the Model

There are two ways to find the Model provided by the ScopedModel Widget.

  1. Use the ScopedModelDescendant Widget. It will find the Model and run the builder function whenever the Model notifies the listeners.
  2. Use the ScopedModel.of static method directly. To make this method more readable for frequent access, you can consider adding your own of method to your own Model classes like so:
class CounterModel extends Model {
  // ...
 
  /// Wraps [ScopedModel.of] for this [Model].
  static CounterModel of(BuildContext context) =>
      ScopedModel.of<CounterModel>(context);
}

Listening to multiple Models in a build function

In many cases, it makes sense to split your Models apart into logical components by functionality. For example, rather than having an AppModel that contains all of your application logic, it can often make more sense to split models apart into a UserModel, a SearchModel and a ProductModel, for example.

However, if you need to display information from two of these models in a single Widget, you might be wondering how to achieve that! To do so, you have two options:

  1. Use multiple ScopedModelDescendant Widgets
  2. Use multiple ScopedModel.of calls. No need to manage subscriptions, Flutter takes care of all of that through the magic of InheritedWidgets.
class CombinedWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final username =
      ScopedModel.of<UserModel>(context, rebuildOnChange: true).username;
    final counter =
      ScopedModel.of<CounterModel>(context, rebuildOnChange: true).counter;

    return Text('$username tapped the button $counter times');
  }
}

Contributors

Comments
  • Ability to connect multiple models in connector (ScopedModel)

    Ability to connect multiple models in connector (ScopedModel)

    I am a big fan of unstated which takes advantages of React's new Context API and shares many similarities to this library.

    It would be nice if you could combine multiple models in the subscriber

    new ScopedModel(
          model: [new BookModel(), new CounterModel()],
          child: new Column(children: [
            new ScopedModelDescendant(
                    builder: (context, child, { bookModel, counterModel }) => new Text(
                        counterModel.counter.toString()),
                  ),
            new Text("Another widget that doesn't depend on the CounterModel")
          ])
    

    similar to how you can do it in unstated

    <Subscribe to={[BookContainer, CounterContainer]}>
      {
        (bookStore, counterStore) => {
          // do stuff here
        }
      }
    </Subscribe>
    
    opened by chimon2000 31
  • Move to React Context naming

    Move to React Context naming

    React just published the Context API with the same features as scoped_model. I was thinking about changing the names of scoped_model to conform the React names (Which are pretty good).

    ScopedModel<AModel> -> ContextProvider<AModel> ScopedModelDescendant<AModel> -> ContextConsumer<AModel>

    //cc @apwilson

    opened by passsy 15
  • I get an error when mixin 2 models to a main model

    I get an error when mixin 2 models to a main model

    compiler message: lib/scoped-models/main.dart:6:17: Error: The type 'ProductsModel' can't be mixed in.

    compiler message: class MainModel extends Model with UserModel, ProductsModel {}

    compiler message: ^

    compiler message: lib/scoped-models/main.dart:6:47: Error: Type 'ProductsModel' not found.

    compiler message: class MainModel extends Model with UserModel, ProductsModel {}

    compiler message: ^

    compiler message: lib/scoped-models/main.dart:1: Error: The superclass, '_MainModel&Model&UserModel&ProductsModel', has no unnamed constructor that takes no arguments.


    ✓] Flutter (Channel beta, v0.8.2, on Mac OS X 10.13.6 17G2307, locale en-TH) [✓] Android toolchain - develop for Android devices (Android SDK 28.0.1) [✓] iOS toolchain - develop for iOS devices (Xcode 10.0) [✓] Android Studio (version 3.1) [✓] VS Code (version 1.27.2) [✓] Connected devices (1 available)

    opened by ChristBKK 8
  • Cross-platform Support

    Cross-platform Support

    Hey all,

    One downside to scoped_model: It cannot be used for AngularDart / Dart Web apps because Model implements the Listenable interface from Flutter.

    Proposal

    Split scoped_model into 3 packages:

    1. scoped_model would contain only the Model class, which implements no interfaces.
    2. scoped_model_flutter would Import the Model class and use it for the ScopedModel / ScopedModelDescendant Widgets
    3. scoped_model_angular would provide a Pipe that can be used to listen for changes to a Model class, rebuilding the appropriate component on change. e.g. {{(myModel | listen).message}}

    Pros

    Makes the Model class Completely independent of Flutter, and can be re-used cross-platform.

    Cons

    • Can't create a MyModel.of(BuildContext context) method directly on the Model if you want to use the library cross-platform. I don't know how common this is...
    • Not sure if folks are currently using scoped_model as a Listenable (such as with an AnimatedBuilder widget), or merging it with other Listenables via the Listenable.merge constructor.

    Would love to hear your thoughts @passsy, @apwilson, @chimon2000 and others! Is anyone using the Model class as a Listenable?

    opened by brianegan 8
  • How to use load and persist json data in scoped model

    How to use load and persist json data in scoped model

    I am trying to load json data using the scoped model like this:

    import 'package:scoped_model/scoped_model.dart';
    import 'package:flutter/services.dart' show rootBundle;
    
    class MyModel extends Model {
      Map _jsonData;
    
      Future MyModel() async {
        // this won't work 
        String json =  await rootBundle.loadString('assets/words5.json');
         this._jsonData = json.decode(jsonString);
      }
      Map get jsonData => _jsonData;
    }
    
    

    After doing some research on stackoverflow, it was suggested I do something like this:

    class MyModel extends Model {
      Map _jsonData;
      Future _doneFuture;
    
       MyModel()  {
          _doneFuture = _init();
       }
    
      Future _init() async {
        print('init');
        String jsonString = await _loadJsonFile();
        this._jsonData = json.decode(jsonString); 
      }
    
      Map get jsonData => _jsonData;
      Future get initializationDone => _doneFuture;
    
      Future<String> _loadJsonFile() async {
        return await rootBundle.loadString('assets/words.json');
      }
    
    }
    
    Future main() async {
     var c = new MyModel();
     await c.initializationDone;
     print('done');
      Widget app = new ScopedModel<CounterModel>(
     //.. 
    )
    }
    

    Note that rootBundle returns a Future and that is, as far as I know, the only way to load files in Flutter.

    I am running the newest Flutter and Dart 2 (Channel master, v0.3.1-pre.15, on Mac OS X 10.12.6 16G29, locale en-US) . Any idea how to load json data into my scoped model in Flutter?

    opened by pebreo 8
  • Missing docs on best way to instantiate the ScopeModel widget when you have multiple models

    Missing docs on best way to instantiate the ScopeModel widget when you have multiple models

    The "Listening to multiple Models in a build function" doesn't cover how to instantiate the app for the first time, ie there's no multi-model equivalent of:

    class CounterApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        // First, create a `ScopedModel` widget. This will provide 
        // the `model` to the children that request it. 
        return new ScopedModel<CounterModel>(
          model: new CounterModel(),
    

    in the docs :-) Only solutions I found online boil down to creating a God object of all the model objects and then passing it to the main app widget in a ScopedModel<God> call (ie https://proandroiddev.com/you-might-not-need-redux-the-flutter-edition-9c11eba006d7, but also https://www.udemy.com/learn-flutter-dart-to-build-ios-android-apps/learn/v4/t/lecture/12309188?start=0 & others),

    this is the only solution I found so far, I refuse to believe this is the truth (and it doesn't work with newer versions of Dart, you can't instantiate a mixin), so I'm hoping for some sage guidance from the Creators ^_^

    opened by bbozo 7
  • navigate to new route from model

    navigate to new route from model

    Is there a way to navigate to a new route from the model (not from the page widget)?

    I need to navigate out of the screen on some logical condition (as oppose to user action) Is there a way to do it directly from the model logic?

    Currently I setup a flag in the model and use it to show a "finish" button to the user where the navigation happens (onPressed), but I would like to navigate without the user's interaction.

    Thank you

    opened by ronmany 7
  •  Could not find the correct ScopedModel.

    Could not find the correct ScopedModel.

    void main() {
      runApp(new MyApp());
    }
    
    class MyApp extends StatelessWidget {
     @override
      Widget build(BuildContext context) {
        return new MaterialApp(
          home: new HomePage(),
          onGenerateRoute: Routes.onGenerateRoute,
        );
      }
    }
    
    class HomePage extends StatelessWidget {
     @override
      Widget build(BuildContext context) {
        return ScopedModel<SampleScopedModel>(
          model: SampleScopedModel(),
          child: Scaffold(
            body: Container(),
            floatingActionButton: FloatingActionButton(onPressed: () {
              Navigator.pushNamed(context, "NextPage");
            }),
          ),
        );
      }
    }
    
    class NextPage extends StatelessWidget {
      @override
        Widget build(BuildContext context) {
          return ScopedModel<SampleScopedModel>(
            model: SampleScopedModel(),
            child: Scaffold(
              body: ScopedModelDescendant<SampleScopedModel>(
              builder: (context, child, model) {
                return Text(model.payload.toString());
              })
            ),
         );
        }
    }
    
    class SampleScopedModel extends Model {
      int _payload;
    
      int get payload => _payload;
    
      static SampleScopedModel of(BuildContext context) =>
          ScopedModel.of<SampleScopedModel>(context);
    
      void setPayload(int payload) {
        this._payload = payload;
        notifyListeners();
      }
    }
    
    opened by anderscheow 6
  • ScopedModel.of vs ScopedModelDescendant usage

    ScopedModel.of vs ScopedModelDescendant usage

    I think the answers to these questions(mostly related to which widget rebuilds) would be a good extension to the documentation. I suggest we add some clarity with the usage including some advantages/disadvantages in our nice docs

    I.

    @override
    Widget build(BuildContext context) {
      // ScopedModel.of<HomeModel>(context, rebuildOnChange: true); under the hood
      final model = HomeModel.of(context);
      return Scaffold(
        appBar: AppBar(
          title: Text(
            'A = model.countA}
          ),
        ),
      );
    }
    

    Question: Will the whole Scaffold rebuild if model.countA's value changes? If not, which child widget will be rebuilt on value change?

    II.

    a.

    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text(
            'A = HomeModel.of(context).countA}
          ),
        ),
      );
    }
    

    b.

    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: ScopedModelDescendant<HomeModel>(
            builder: (context, child, model) => Text(
              'A = ${model.countA}'
            ),
          ),
        ),
      );
    }
    

    Question: Will a and b rebuild the same widget? Which is more performant?

    opened by Edorin9 4
  • TextFormField resets model

    TextFormField resets model

    If you use a combination of TextFormFields and Int counters when the text field gets focused the model gets reset.

    Model:

    import 'package:flutter/material.dart';
    import 'package:scoped_model/scoped_model.dart';
    
    import '../../util/format_money.dart';
    
    class TipCalcModel extends Model {
      int _tip = 18;
      int _people = 1;
      double _bill = 0.0;
    
      int get tip => _tip;
      int get people => _people;
      double get bill => _bill;
    
      set tip(int value) {
        _tip = value;
        notifyListeners();
      }
    
      set people(int value) {
        _people = value;
        notifyListeners();
      }
    
      set bill(double value) {
        _bill = value;
        notifyListeners();
      }
    
      double _calcTip() {
        return (((tip ?? 18.0) / 100) * _bill) / _people;
      }
    
      String calcTipTotal() {
        return formatMoney(_calcTip());
      }
    
      String calcBillTotal() {
        double _amountTotal = (_calcTip() + _bill) / _people;
        return formatMoney(_amountTotal);
      }
    }
    

    Screen:

    import 'dart:async';
    
    import 'package:flutter/material.dart';
    import 'package:flutter/rendering.dart';
    import 'package:font_awesome_flutter/font_awesome_flutter.dart';
    import 'package:native_widgets/native_widgets.dart';
    import 'package:scoped_model/scoped_model.dart';
    
    import '../../models/calcs/tip.dart';
    import '../../util/dismiss_keyboard.dart';
    import '../../util/new_line.dart';
    import '../../util/popUp.dart';
    import '../../widgets/circle_icon.dart';
    import '../../widgets/spacer.dart';
    
    class TipCalculator extends StatelessWidget {
      static String routeName = "/tip_calc";
    
      static final GlobalKey<FormState> formKey = GlobalKey<FormState>();
      static final GlobalKey<FormFieldState<String>> billKey =
          GlobalKey<FormFieldState<String>>();
    
      @override
      Widget build(BuildContext context) {
        return new ScopedModel<TipCalcModel>(
          model: TipCalcModel(),
          child: Scaffold(
            appBar: AppBar(
              title: Text(
                'Tip Calculator',
                style: Theme.of(context)
                    .textTheme
                    .headline
                    .copyWith(color: Colors.white),
              ),
              elevation: 0.0,
            ),
            body: ScopedModelDescendant<TipCalcModel>(
              builder: (context, child, model) => SafeArea(
                    child: Padding(
                      padding: const EdgeInsets.all(16.0),
                      child: ListView(children: <Widget>[
                        Form(
                          key: formKey,
                          autovalidate: false,
                          onWillPop: () {
                            return Future(() => true);
                          },
                          child: ListTile(
                            leading: Icon(FontAwesomeIcons.moneyBill),
                            title: TextFormField(
                              key: billKey,
                              autofocus: true,
                              style: Theme.of(context).textTheme.headline,
                              keyboardType: TextInputType.numberWithOptions(),
                              decoration: InputDecoration(labelText: 'Bill Total'),
                              validator: (val) => val.trim().isEmpty
                                  ? 'Total of the Bill Required'
                                  : null,
                            ),
                          ),
                        ),
                        spacer,
                        ListTile(
                          leading: Icon(FontAwesomeIcons.percentage),
                          title: Text(
                            model.tip.toString() + "%",
                            maxLines: 1,
                            style: Theme.of(context)
                                .textTheme
                                .display1
                                .copyWith(fontSize: 27.0),
                          ),
                          onTap: () {
                            showAlertPopup(context, "Info",
                                "Tip Amount. $newLine\Averages 18-20 %");
                          },
                          trailing: ButtonBar(
                            mainAxisSize: MainAxisSize.min,
                            children: <Widget>[
                              circleIconButton(
                                  icon: FontAwesomeIcons.minus,
                                  onPressed:
                                      model.tip == 0 ? null : () => model.tip--),
                              circleIconButton(
                                  icon: FontAwesomeIcons.plus,
                                  onPressed:
                                      model.tip == 100 ? null : () => model.tip++),
                            ],
                          ),
                        ),
                        spacer,
                        ListTile(
                          leading:
                              Icon(model.people == 1 ? Icons.person : Icons.people),
                          title: Text(
                            model.people.toString(),
                            style: Theme.of(context)
                                .textTheme
                                .display1
                                .copyWith(fontSize: 27.0),
                          ),
                          onTap: () {
                            var _message =
                                "Number of People to Split the Check With.$newLine";
                            if (model.people == 1) {
                              _message += " Currently just you.";
                            } else if (model.people == 2) {
                              _message +=
                                  " Currently you plus ${model.people - 1} other person.";
                            } else {
                              _message +=
                                  " Currently you plus ${model.people - 1} people.";
                            }
                            showAlertPopup(context, "Info", _message);
                          },
                          trailing: ButtonBar(
                              mainAxisSize: MainAxisSize.min,
                              children: <Widget>[
                                circleIconButton(
                                    icon: FontAwesomeIcons.minus,
                                    onPressed: model.people == 1
                                        ? null
                                        : () => model.people--),
                                circleIconButton(
                                    icon: FontAwesomeIcons.plus,
                                    onPressed: () => model.people++),
                              ]),
                        ),
                        spacer,
                        NativeButton(
                          onPressed: () {
                            final _bill = billKey.currentState.value;
                            model.bill = double.tryParse(_bill);
                            final form = formKey.currentState;
                            if (form.validate()) {
                              dismissKeyboard(context);
                              showModalBottomSheet<void>(
                                  context: context,
                                  builder: (BuildContext context) {
                                    return SafeArea(
                                        child: Column(
                                      mainAxisSize: MainAxisSize.min,
                                      children: <Widget>[
                                        ListTile(
                                          title: Text(
                                            model.people == 1
                                                ? "Amount Due"
                                                : "Per Person",
                                            style: Theme.of(context)
                                                .textTheme
                                                .headline,
                                          ),
                                        ),
                                        ListTile(
                                          leading:
                                              Icon(FontAwesomeIcons.percentage),
                                          title: Text(
                                            "Tip: " + model.calcTipTotal(),
                                            style: Theme.of(context)
                                                .textTheme
                                                .headline,
                                          ),
                                        ),
                                        ListTile(
                                          leading: Icon(FontAwesomeIcons.moneyBill),
                                          title: Text(
                                            "Total: " + model.calcBillTotal(),
                                            style: Theme.of(context)
                                                .textTheme
                                                .headline,
                                          ),
                                        ),
                                        ListTile(
                                          leading: Icon(Icons.info),
                                          title: Text(
                                            "Increase the Tip Percentage for Good Service",
                                            style:
                                                Theme.of(context).textTheme.body1,
                                          ),
                                          subtitle: Text(
                                            'Poor: 16%, Good: 18%, Great: 20%',
                                          ),
                                        ),
                                      ],
                                    ));
                                  });
                            }
                          },
                          buttonColor: Colors.blue,
                          child: Text('Calculate'),
                        ),
                      ]),
                    ),
                  ),
            ),
          ),
        );
      }
    }
    
    opened by rodydavis 4
  • Add SomeModel.of(context) documentation to Readme

    Add SomeModel.of(context) documentation to Readme

    There are two ways to access a scoped model:

    1. via ScopedModelDescendant builder
    2. with static SomeMode.of(context) function

    The second one is not documented in the Readme

    opened by passsy 4
  • Target of URI doesn't exist: 'package:scoped_model/scoped_model.dart'.

    Target of URI doesn't exist: 'package:scoped_model/scoped_model.dart'.

    Target of URI doesn't exist: 'package:scoped_model/scoped_model.dart'. Try creating the file referenced by the URI, or Try using a URI for a file that does exist.darturi_does_not_exist

    opened by nabinsah703 0
  • Not Working error

    Not Working error

    return ScopedModelDescendant( builder: (context, child, model) { return Card( child: Column( children: [ Image.network( 'http://192.168.29.11/apisync/image/product/' + _product[index]['img'], fit: BoxFit.fill, height: 350.0, width: 1000.0, ), Text(_product[index].name, style: TextStyle(fontWeight: FontWeight.bold),), Text("$"+_product[index].price.toString()), RaisedButton( child: Text("Add"), onPressed: () => model.addProduct(_product[index])) ])); });

    opened by afsatechnical 0
  • Model notifyListeners closes EndDrawer

    Model notifyListeners closes EndDrawer

    My app's home page opens an EndDrawer in a ScopedModelDescendant for editing app settings. When the user makes a change affecting the main page widgets, the drawer widget calls a model method which uses notifyListeners to keep the main UI up to date. The problem is that this immediately closes the EndDrawer. If I don't call notifyListeners in this way, the main UI is stale when the drawer closes.

    opened by cedarbob 0
  • Scoped Model - not working after go back to previous page

    Scoped Model - not working after go back to previous page

    When I open the app. The app will call _callAPI() async {} since I put it in init. Then I click counter++ to add the value. Then it will show the added value in screen.then submit go to next page. when I click back page. The page will call the API then suddenly my scope model not working. when I try add value. The value not change.when I print in debug console. It did added the value.but It does not change in my screen. I think the problem is my scope model not working anymore in my app.

    main.dart`class MyApp extends StatelessWidget { @override Widget build(BuildContext context) {

    final MainModel _model = MainModel();
    return ScopedModel<MainModel>(
      model: _model,
        child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    ),
    );
    

    } }

    class _MyHomePageState extends State {

    @override void initState(){ super.initState(); fetchList().then((value){ setState(() { _callAPI(); }); }); }

    _callAPI() async { try{ String dataURL = "url"; http.Response response = await http.get(dataURL); } on Exception{ } }

    Widget build(BuildContext context) { return ScopedModelDescendant( builder: (BuildContext context, Widget child, MainModel model) { return Scaffold( appBar: AppBar( title: appBarTitle, centerTitle: true, actions: [ Stack( children: [ new IconButton(icon: Icon(Icons.card_travel), onPressed: () { Navigator.push( context, MaterialPageRoute(builder: (context) => cartPage()), ); }), Container( child: model.list.length != 0 ? new Positioned( right: 11, top: 11, child: new Container( padding: EdgeInsets.all(2), decoration: new BoxDecoration( color: Colors.red, borderRadius: BorderRadius.circular(6), ), constraints: BoxConstraints( minWidth: 16, minHeight: 16, ), child: Text( "${model.list.length}", style: TextStyle( color: Colors.white, fontSize: 12, ), textAlign: TextAlign.center, ), ), ) : new Container() ), ], ), ], backgroundColor: getMainColor(), elevation: 10.0, ), drawer: new Drawer( child: _drawerLeft(context), ), body: Container( ), );} );}

    Widget addValue{
          return Padding(
                   padding: EdgeInsets.fromLTRB(9, 0, 0, 0),
                         child: SizedBox (
                             height:35,
                             width:35,
                             child: FloatingActionButton(   
                             heroTag: "addM",               
                                onPressed: () {
                                        Map setValue = {"var1 " : var1};          
                                        model.addInList(setValue);
    				Navigator.push(
                  				context,
                  				MaterialPageRoute(builder: (context) => nextPage()),
                			);
                                },
                                child: Icon(
                                        Icons.add_circle_outline,
                                        color: Colors.white,
                                        size: 19,
                                ),
                             backgroundColor: getMainColor(),     
                      ),
                   ),
          )
    }
    

    }`

    scoped_models\main.dart `List _list=[];

    List get list{ return _list; }

    void addInList(Map newList){ _list.insert(0, newList); notifyListeners(); } `

    opened by syazie 0
Owner
Brian Egan
Montana boy living in Berlin, Indie Hacker, and speaker of bad German.
Brian Egan
A Flutter library for work with Apple Wallet passes.

pass-flutter A Flutter library for work with Apple Wallet passes. How use it Getting pass from URL to internal memory import 'package:pass_flutter/pas

Alexey Lepskii 16 Dec 30, 2022
A modular app architecture that can be scalable as the time passes

A modular app architecture that can be scalable as the time passes. I will be using the BLoC state-management package.

Md. Siam 62 Dec 25, 2022
An all-in-one Fllutter package for state management, reactive objects, animations, effects, timed widgets etc.

Frideos An all-in-one package for state management, streams and BLoC pattern, animations and timed widgets, effects. Contents 1. State management Gett

Francesco Mineo 188 Dec 23, 2022
Hassan 1 Sep 27, 2022
Do It Right - flutter app, simple android game to Increase Children’s Intention and Behavior About Littering

doitright "DoItRight": An Arabic Flutter Mobile App to Increase Children’s Inten

Yasser Alsleman 0 Jan 23, 2022
A flutter widget which renders its child outside the original widget hierarchy.

overlay_container A flutter widget which renders its child outside the original widget hierarchy. Demo. This demo is present as an example here. You c

Mustansir Zia 30 Jun 10, 2022
The Reactive Extensions for Dart

RxDart About RxDart extends the capabilities of Dart Streams and StreamControllers. Dart comes with a very decent Streams API out-of-the-box; rather t

ReactiveX 3.2k Dec 20, 2022
Learn how to build a tensorflow model on Techable Machine and then run it on flutter app.

Ml With Flutter Learn how to build a tensorflow model on Techable Machine and then run it on flutter app. Youtube Tutorial Show Support Recommend Me O

Sanskar Tiwari 133 Jan 3, 2023
Flutter App Build for the machine Learning model which shows sentiments of instagram user by analysing their captions

InstaKnow Front-end By @ketanchoyal Back-end By @namas191297 Front-end Application Flutter application that allows user to analyze sentiments of other

Ketan Choyal 40 Oct 28, 2022
Nexus is a state management library that makes it easy to create and consume your application's reactive data to the user interface.

Nexus ?? Nexus is a state management library that makes it easy to create and consume your application's reactive data to the user interface. With nex

Gor Mkhitaryan 3 Sep 7, 2022
[Flutter Library] Flamingo is a firebase firestore model framework library. 🐤

Flamingo Flamingo is a firebase firestore model framework library. https://pub.dev/packages/flamingo 日本語ドキュメント Example code See the example directory

shohei 117 Sep 22, 2022
This is machine learning project where developed the model in teachable machine.

doc_help A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started if this

Abu sayed chowdhury 1 Apr 26, 2022
The typesafe, reactive, and lightweight SQLite abstraction for your Flutter applications

See the project's website for the full documentation. Floor provides a neat SQLite abstraction for your Flutter applications inspired by the Room pers

Vitus 786 Dec 28, 2022
Nimbostratus is a reactive data-fetching and client-side cache management library built on top of Cloud Firestore.

Nimbostratus ?? Nimbostratus is a reactive data-fetching and client-side cache management library built on top of Cloud Firestore. The Cloud Firestore

Dan Reynolds 13 Dec 15, 2022
A chat application that utilizes the smart reply ML model to suggest contextual conversation replies.

smart_reply A chat application that utilizes the smart reply ML model to suggest contextual conversation replies. Sample Notes Smart Replies are conte

Ahmed Aboelyazeed 1 May 15, 2022
This is simple model replication i made in flutter

This is simple model replication i made in flutter

sushil gyawali 3 Sep 20, 2022
An example of "reactive/streaming repository" as a solution for BLoC to BLoC communication

Reactive Repositories An example of listening to a Stream from repository layer (instead of explicitly using get/fetch) as a solution for BLoC to BLoC

Sandro Lovnički 11 Jan 3, 2023
A light, powerful and reactive state management for Flutter Apps.

A light, powerful and reactive state management. Features ⚡️ Build for speed. ?? Reduce boilerplate code significantly. ?? Improve code readability. ?

2devs 3 Dec 15, 2022