flutter / website

Flutter documentation web site
https://docs.flutter.dev
Other
2.75k stars 3.17k forks source link

Better state management solution #2012

Closed zoechi closed 5 years ago

zoechi commented 5 years ago

@Michael77 commented on Thu Jul 06 2017

The largest problem I have encountered so far using the Flutter framework is state management. The documentation only provides examples of handling state in the same component and the parent component, but this is not suitable for a complex application. I came up with the solution of passing a shared state class to each of my pages, but that was unreliable and didn't scale very well as I added more pages. Next I tried using the flutter_flux library, but it appears that I need to store all of the pages variables in a single store because I can't call setState() when I am using this lib.

Is there a better way of doing things? I am accustomed to doing things the 'angular way' where I share state between components by putting it in shared services and utilizing observables.

I am only asking this here because it appears to be the weakest point in the framework, and is hardly discussed on stackoverflow or any other forum.


@eseidelGoogle commented on Thu Jul 06 2017

Historically Flutter has not tried to express an opinion as to ones whole-app architecture, but understandably you are asking (and many others have asked) for a bit more guidance here.

Our existing customers have explored a variety of approaches. It's possible that @mehmetf or @gavindoughtie have recommendations here.

FYI @Hixie


@animeshjain commented on Sat Aug 12 2017

+1 Hello, can anyone please provide recommendations here. I have been kind of stuck myself trying to figure out if there are certain recipes for state management in complex apps.


@branflake2267 commented on Sat Aug 12 2017

One thing I like to keep in mind when thinking about state management is the page lifecycle. So I think of each page as a unit that may share global persistence variables. These variables can retain the state of how I want to express my logic through the UI. This world doesn't have as much structure as the base apis, so it's expressed through my intent. And I have noticed everybody likes to choose their own path. That said, I have some options I like to choose when I want to persist state across multiple pages or the application. I like to keep things simple and express my application state in long term state variables. And I'll persist these in different ways depending on my application.

So overall, I think state management is pretty easy to deal with. It's a matter of how I want to structure my longer term persistence variables which affect my business logic across the application. And this all depends on how I structure authentication, security, and then how my business logic flows. So for me there isn't any reason for state management to be any different for complex large application vs. small instructional applications because state is retained in longer term variables.

Although transferring into Flutter application, what caught me up is changing state in the application and how can I do this. So I'll wire up handlers to listen for changes and fire off setState when the are fired. And then there are async calls, how do you deal with those. I found a FutureBuilder was a fantastic way to wire up a call, and at the end of it calls setState.

So overall I think of it like this. The application's UI reacts to the changes in short and long term variables. The widget pattern and how the UI is rendered is one of the coolest things about flutter.

Best of luck in your state management.


@ColquePaxi commented on Tue Dec 11 2018

For a newbie manage states it's so hard.

I loved Firebase, GoogleSignIn, Auth_Firebase to manage LogIn/LogOut.

Flutter is a wonderful SDK... the learning curve it's fantastic.

But, would be interesting have a best way to manage the return for Future / async (if not yet exist... I'm a newbie).

For example, imagine the WhatsApp interface: how to list de talks when user run the App?

The talks' list is on Firebase - Realtime Database (future / async).

Structure:
TALKS -> UserLoggedEmail -> Talk01 Talk02 Talk03

The problem here is: how to get the UserLoggedEmail by FirebaseAuth (Future/async) before create my TalksPage?

In this code bellow, I don't found a simple way to pass a updated variable to another page when the variable depend Future/async finished. How to do it?

import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';

// Variável de controle de Autenticação Google
final googleSignIn = new GoogleSignIn();

// Variável para gerenciar a Autenticação com o Google Firebase
final auth = FirebaseAuth.instance;

String _loggedUser = "INITIAL VALUE";
String _loggedUserTitle = "NEW TITLE";

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  int _counter = 0;

  @override
  initState() {
    super.initState();
    mostraUID();
  }

  Future<Null> mostraUID() async {

    print("Entrei na mostraUID");

    GoogleSignInAccount user = googleSignIn.currentUser;
    if(user == null)
      user = await googleSignIn.signInSilently();
    if(user == null) {
      user = await googleSignIn.signIn();
    }

    // O gerenciamento de TOKEN é implícito
    if(await auth.currentUser() == null) {
      GoogleSignInAuthentication credentials = await googleSignIn.currentUser.authentication;
      await auth.signInWithGoogle(
        idToken: credentials.idToken,
        accessToken: credentials.accessToken,
      );
    }

    _loggedUser = user.email;

    FirebaseUser userFirebase = await FirebaseAuth.instance.currentUser();
    print("User no Firebase: " + userFirebase.uid);
    print("User no GoogleSignIn: " + user.email);

  }

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {

    print("Entrei no Widget build(Build Context context)");

    setState(() {
      _loggedUserTitle = _loggedUser;
    });

    return new Scaffold(
      appBar: new AppBar(
        //title: new Text(widget.title),

        // *************************************************************************************************** //
        // I'll use "message/$_loggedUser" to compose my database reference (Firebase) to show user's messages
        title: new Text(_loggedUserTitle),
        // *************************************************************************************************** //

      ),
      body: new Center(
        child: new Text(
          'Button tapped $_counter time${ _counter == 1 ? '' : 's' }.',
        ),
      ),
      floatingActionButton: new FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: new Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }

}

It's works fine after I click on FAB.

This problem can be very simple, but I imagine it's a common use case where need a more examples to desmistify it.

Thanks a lot.


@theankurkedia commented on Wed Jan 31 2018

@ColquePaxi I think you can solve this by using setState() inside mostraUID() when the user is signed in. And it is happening because you are using it inside build() which executes for the first time before completing the async operation. So, you only get the logged-in user when you use setState() the next time, which happens when you click on FAB.


@ColquePaxi commented on Tue Dec 11 2018

@theankurkedia The step1 (way to pass a updated variable to another page when the variable depend Future/async finished) works fine. Thanks!!! But step2 (how to get the UserLoggedEmail by FirebaseAuth (Future/async) before create my TalksPage?) no...

See new implementation:

import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:firebase_database/ui/firebase_animated_list.dart';

// Para usar o Base64Encoder e o Base64Decoder
import 'dart:convert';

// Variável de controle de Autenticação Google
final googleSignIn = new GoogleSignIn();

// Variável para gerenciar a Autenticação com o Google Firebase
final auth = FirebaseAuth.instance;

String _loggedUser = "INITIAL VALUE";
String _loggedUserTitle = "NEW TITLE";
String _loggedUserEncoded = "";

// Variável global para identificar NÓ + usuário que está logado
String _referenceString = "";
DatabaseReference _reference;

// Variável global para identificar a cotacao escolhida pelo usuário que está logado
String _cotacaoEscolhida = "";
String _emailCotacaoEscolhida = "";
String _emailCotacaoEscolhidaEncoded = "";

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  int _counter = 0;

  @override
  initState() {
    super.initState();
    mostraUID();
  }

  Future<Null> mostraUID() async {

    print("Entrei na mostraUID");

    GoogleSignInAccount user = googleSignIn.currentUser;
    if(user == null)
      user = await googleSignIn.signInSilently();
    if(user == null) {
      user = await googleSignIn.signIn();
    }

    // O gerenciamento de TOKEN é implícito
    if(await auth.currentUser() == null) {
      GoogleSignInAuthentication credentials = await googleSignIn.currentUser.authentication;
      await auth.signInWithGoogle(
        idToken: credentials.idToken,
        accessToken: credentials.accessToken,
      );
    }

    setState(() {
      _loggedUser = user.email;
      _loggedUserEncoded = BASE64.encode(UTF8.encode(_loggedUser));
      _referenceString = "conversas/" + _loggedUserEncoded;
    });

    FirebaseUser userFirebase = await FirebaseAuth.instance.currentUser();
    print("User Firebase: " + userFirebase.uid);
    print("User GoogleSignIn: " + user.email);
    print("setState mostraUID = _referenceString atualizado: " + _referenceString);

  }

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {

    print("Entrei no Widget build(Build Context context)");

    setState(() {
      _loggedUserTitle = _loggedUser;
      _reference = FirebaseDatabase.instance.reference().child(_referenceString);
    });

    print("Widget build :  _reference.path: " + _reference.path.toString());

    return new Scaffold(
      appBar: new AppBar(
        //title: new Text(widget.title),

        // *************************************************************************************************** //
        // I'll use "message/$_loggedUser" to compose my database reference (Firebase) to show user's messages
        title: new Text(_referenceString),
        // *************************************************************************************************** //

      ),
      body: new Container(  // Cap8: Enrole o nível superior Columnem um Containerwidget para dar uma borda cinza claro na sua extremidade superior. Esta borda ajudará a distinguir visualmente a barra do aplicativo do corpo do aplicativo no iOS.
          color: Colors.yellow[100],
          child: new Column(
            children: <Widget>[
              _buildListChat(),
              new Container(/* Teste */),
            ],
          ),
          // A parte de cima foi encapsulada num Container para que essa debaixo tenha umas bordas distintas no iOS
          decoration: Theme.of(context).platform == TargetPlatform.iOS
              ? new BoxDecoration(
              border: new Border(top: new BorderSide(color: Colors.grey[100]))
          )
              : null

      ), // Fecha o body: new Container
      floatingActionButton: new FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: new Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }

}

/*************************** CLASSES PARA SUPORTE - INÍCIO *************************************/

class CotacoesConversa extends StatelessWidget {

  final DataSnapshot snapshot;
  final Animation animation;

  CotacoesConversa({this.snapshot, this.animation});

  @override
  Widget build(BuildContext context) {

    print("classe CotacoesConversa: " + snapshot.value.toString());

    // Se não der certo, fazer um IF ou ?: para condicionar o return
    // if(snapshot.value["senderName"] != userLoggedEmailEncoded.getUserEmailEncoded)
    return new SizeTransition(
      sizeFactor: new CurvedAnimation(parent: animation, curve: Curves.easeOut),
      axisAlignment: 0.0,
      child: new Container(
        margin: const EdgeInsets.symmetric(vertical: 15.0),
        child: new Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            new Container(
              margin: const EdgeInsets.only(right: 16.0),
              child: new CircleAvatar(
                backgroundImage: new NetworkImage(
                    snapshot.value["senderPhotoUrl"]),
              ),
            ),
            new Expanded(
              child: new Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  new Text(
                    snapshot.value["senderName"],
                    style: Theme
                        .of(context)
                        .textTheme
                        .subhead,
                  ),
                  new Container(
                    margin: const EdgeInsets.only(top: 5.0),
                    child: snapshot.value["imageUrl"] != null
                        ? new Image.network(
                      snapshot.value["imageUrl"],
                      width: 250.0,
                    )
                        : new Text(snapshot.value["text"]),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

}

/*************************** CLASSES PARA SUPORTE - FINAL *************************************/

Widget _buildListChat() {
  return
    new Flexible(
      child: new FirebaseAnimatedList(
        query: _reference,  // O nó inicial do Firebase
        padding: new EdgeInsets.all(8.0),
        itemBuilder: (_, DataSnapshot snapshot, Animation<double> animation){
          return new ListTile(
            title: new CotacoesConversa(
              snapshot: snapshot,
              animation: animation,
            ),
            onTap: () {
              print("Você clicou no " + snapshot.value["text"]);
              _cotacaoEscolhida = snapshot.value["text"];
              _emailCotacaoEscolhida = snapshot.value["senderEmail"];
              print("Cliquei no LIST e atualizei a _emailCotacaoEscolhida para: " + _emailCotacaoEscolhida);
            },
          );
        },
      ),
    ); // Fecha com Flexible
}

See run log:

Performing full restart...
Restarted app in 3.895ms.
I/flutter ( 3674): Entrei no Widget build(Build Context context)
I/flutter ( 3674): Widget build :  _reference.path: 
I/flutter ( 3674): Entrei na mostraUID
W/SyncTree( 3674): Listen at / failed: DatabaseError: Permission denied
I/flutter ( 3674): User Firebase: BMFGDOmwwjgALMSEZDN8f0gnap83
I/flutter ( 3674): User GoogleSignIn: colque@gmail.com
I/flutter ( 3674): setState mostraUID = _referenceString atualizado: conversas/Y29scXVlQGdtYWlsLmNvbQ==
I/flutter ( 3674): Entrei no Widget build(Build Context context)
I/flutter ( 3674): Widget build :  _reference.path: conversas/Y29scXVlQGdtYWlsLmNvbQ==

See that _reference.path: 1) It's null because Widget build is ran before finished mostraUID (therefore my query on FirebaseAnimatedList don't have nothing - no have path - to show me datas). It's the Database error cause. 2) When finishes mostraUID, _reference.path is updated... but how to call Widget built again?

It seems to me that FutureBuilder could be a solution, but I don't know how to implement.


@theankurkedia commented on Thu Feb 01 2018

@ColquePaxi Maybe you can check if the snapshot and its value is null and show a loader if true, otherwise populate the list with the data. You can check this. I have done it this way.


@ColquePaxi commented on Tue Dec 11 2018

@theankurkedia I still can not update the value of the Firebase path. Could you show me how to pass updated conversasDatabaseReference to main.dart? Where's the wrong? Only this is missing to solve.

See new codes:

/// globalStore.dart
import 'dart:async';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:firebase_auth/firebase_auth.dart';

final googleSignIn = new GoogleSignIn();
final auth = FirebaseAuth.instance;
final databaseReference = FirebaseDatabase.instance.reference();
GoogleSignInAccount user;
var userDatabaseReference;
var conversasDatabaseReference;

Future<Null> _ensureLoggedIn() async {
  user = googleSignIn.currentUser;
  if (user == null) {
    user = await googleSignIn.signInSilently();
  }
  if (user == null) {
    user = await googleSignIn.signIn();
    userDatabaseReference = databaseReference.child(user.id);
    //articleDatabaseReference = databaseReference.child(user.id).child('articles');
    conversasDatabaseReference = databaseReference.child('conversas').child(user.id);
  }
  if (await auth.currentUser() == null) {
    GoogleSignInAuthentication credentials =
    await googleSignIn.currentUser.authentication;
    await auth.signInWithGoogle(
      idToken: credentials.idToken,
      accessToken: credentials.accessToken,
    );
  } else {
    userDatabaseReference = databaseReference.child(user.id);
    //articleDatabaseReference = databaseReference.child(user.id).child('articles');
    conversasDatabaseReference = databaseReference.child('conversas').child(user.id);
  }
}

var logIn = _ensureLoggedIn();

I used same you:

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:firebase_database/ui/firebase_animated_list.dart';
import './globalStore.dart' as globalStore;

String _cotacaoEscolhida = "";
String _emailCotacaoEscolhida = "";
String _emailCotacaoEscolhidaEncoded = "";

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  int _counter = 0;

  DataSnapshot snapshot;

  Future updateSnapshot() async {
    var snap = await globalStore.conversasDatabaseReference.once();
    this.setState(() {
      snapshot = snap;
    });
    return "Success!";
  }

  @override
  void initState() {
    super.initState();
    this.updateSnapshot();
  }

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(globalStore.conversasDatabaseReference.path.toString()),
      ),
      body: new Container(
          color: Colors.yellow[100],
          child: new Column(
            children: <Widget>[
              _buildListConversa(),
              new Container(/* Teste */),
            ],
          ),
          decoration: Theme.of(context).platform == TargetPlatform.iOS
              ? new BoxDecoration(
              border: new Border(top: new BorderSide(color: Colors.grey[100]))
          )
              : null
      ), // Fecha o body: new Container
      floatingActionButton: new FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: new Icon(Icons.add),
      ),
    );
  }

}

/******************** MÉTODO QUE MOSTRA AS CONVERSAS EM UMA LISTA - INÍCIO ********************/
Widget _buildListConversa() {

  print('caminhoFirebase no _buildListConversa => ' + globalStore.conversasDatabaseReference.path.toString());

  return
    new Flexible(
      child: new FirebaseAnimatedList(
        query: FirebaseDatabase.instance
            .reference()
            .child(globalStore.conversasDatabaseReference.path.toString()),
        padding: new EdgeInsets.all(8.0),
        itemBuilder: (_, DataSnapshot snapshot, Animation<double> animation){
          return new FutureBuilder<DataSnapshot>(
            future: FirebaseDatabase.instance
                .reference()
                .child(globalStore.conversasDatabaseReference.path.toString())
                .once(),
              builder: (BuildContext context, AsyncSnapshot<DataSnapshot> conversaSnap) {
                switch (conversaSnap.connectionState) {
                  case ConnectionState.none:
                    return new Text('Loading...');
                  case ConnectionState.waiting:
                    return new Text('Awaiting result...');
                  default:
                    if (conversaSnap.hasError)
                      return new Text(
                          'Error: ${conversaSnap.error}');
                    else
                      return new ListTile(
                        title:
                        new CotacoesConversa(
                          snapshot: snapshot,
                          animation: animation
                        ),
                        onTap: () {
                          print("Você clicou no " + snapshot.value["text"]);
                          _cotacaoEscolhida = snapshot.value["text"];
                          _emailCotacaoEscolhida = snapshot.value["senderEmail"];
                          print("Cliquei no LIST e atualizei a _emailCotacaoEscolhida para: " + _emailCotacaoEscolhida + " " + _cotacaoEscolhida);
                        },
                      );
              }
            },
          );
        },
      ),
    ); // Fecha com Flexible
}
/******************** MÉTODO QUE MOSTRA AS CONVERSAS EM UMA LISTA - FINAL ********************/

/*************************** CLASSES PARA SUPORTE - INÍCIO *************************************/

class CotacoesConversa extends StatelessWidget {

  CotacoesConversa({this.snapshot, this.animation});
  final DataSnapshot snapshot;
  final Animation animation;

  @override
  Widget build(BuildContext context) {

    print("classe CotacoesConversa: " + snapshot.value.toString());

    return new SizeTransition(
      sizeFactor: new CurvedAnimation(parent: animation, curve: Curves.easeOut),
      axisAlignment: 0.0,
      child: new Container(
        margin: const EdgeInsets.symmetric(vertical: 15.0),
        child: new Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            new Container(
              margin: const EdgeInsets.only(right: 16.0),
              child: new CircleAvatar(
                backgroundImage: new NetworkImage(
                    snapshot.value["senderPhotoUrl"]),
              ),
            ),
            new Expanded(
              child: new Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  new Text(
                    snapshot.value["senderName"],
                    style: Theme
                        .of(context)
                        .textTheme
                        .subhead,
                  ),
                  new Container(
                    margin: const EdgeInsets.only(top: 5.0),
                    child: snapshot.value["imageUrl"] != null
                        ? new Image.network(
                      snapshot.value["imageUrl"],
                      width: 250.0,
                    )
                        : new Text(snapshot.value["text"]),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

}

/*************************** CLASSES PARA SUPORTE - FINAL *************************************/

@ColquePaxi commented on Fri Feb 02 2018

log errors:

Performing full restart...
Restarted app in 3.065ms.
I/flutter ( 3049): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter ( 3049): The following NoSuchMethodError was thrown building MyHomePage(dirty, state:
I/flutter ( 3049): _MyHomePageState#5e328):
I/flutter ( 3049): The getter 'path' was called on null.
I/flutter ( 3049): Receiver: null
I/flutter ( 3049): Tried calling: path
I/flutter ( 3049): When the exception was thrown, this was the stack:
I/flutter ( 3049): #0      Object.noSuchMethod (dart:core-patch/dart:core/object_patch.dart:46)
I/flutter ( 3049): #1      _MyHomePageState.build (/data/user/0/com.yourcompany.merlin/cache/merlinCBXTTZ/merlin/lib/main.dart:68:64)
I/flutter ( 3049): #2      StatefulElement.build (package:flutter/src/widgets/framework.dart:3634:27)
I/flutter ( 3049): #3      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3544:15)
I/flutter ( 3049): #4      Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #5      ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #6      StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3662:22)
I/flutter ( 3049): #7      ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #8      Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #9      Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #10     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #11     Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #12     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #13     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #14     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #15     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #16     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #17     Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #18     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #19     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #20     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #21     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #22     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4532:14)
I/flutter ( 3049): #23     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #24     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #25     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4532:14)
I/flutter ( 3049): #26     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #27     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #28     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #29     Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #30     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #31     StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3662:22)
I/flutter ( 3049): #32     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #33     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #34     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #35     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #36     Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #37     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #38     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #39     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #40     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #41     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4532:14)
I/flutter ( 3049): #42     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #43     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #44     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4532:14)
I/flutter ( 3049): #45     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #46     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #47     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #48     Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #49     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #50     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #51     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #52     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #53     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4532:14)
I/flutter ( 3049): #54     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #55     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #56     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #57     Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #58     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #59     StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3662:22)
I/flutter ( 3049): #60     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #61     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #62     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #63     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #64     Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #65     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #66     StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3662:22)
I/flutter ( 3049): #67     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #68     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #69     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #70     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #71     Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #72     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #73     StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3662:22)
I/flutter ( 3049): #74     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #75     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #76     MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4637:32)
I/flutter ( 3049): #77     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #78     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #79     _TheatreElement.mount (package:flutter/src/widgets/overlay.dart:493:16)
I/flutter ( 3049): #80     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #81     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #82     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #83     Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #84     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #85     StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3662:22)
I/flutter ( 3049): #86     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #87     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #88     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #89     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #90     Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #91     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #92     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #93     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #94     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #95     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4532:14)
I/flutter ( 3049): #96     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #97     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #98     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #99     Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #100    ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #101    StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3662:22)
I/flutter ( 3049): #102    ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #103    Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #104    Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #105    SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4532:14)
I/flutter ( 3049): #106    Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #107    Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #108    SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4532:14)
I/flutter ( 3049): #109    Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #110    Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #111    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #112    Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #113    ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #114    StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3662:22)
I/flutter ( 3049): #115    ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #116    Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #117    Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #118    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #119    Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #120    ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #121    ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #122    Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #123    Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #124    SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4532:14)
I/flutter ( 3049): #125    Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #126    Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #127    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #128    Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #129    ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #130    ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #131    Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #132    Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #133    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #134    Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #135    ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #136    ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #137    Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #138    Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #139    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #140    Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #141    ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #142    ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #143    Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #144    Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #145    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
E/flutter ( 3049): [ERROR:topaz/lib/tonic/logging/dart_error.cc(16)] Unhandled exception:
E/flutter ( 3049): NoSuchMethodError: The method 'once' was called on null.
E/flutter ( 3049): Receiver: null
E/flutter ( 3049): Tried calling: once()
E/flutter ( 3049): #0      Object.noSuchMethod (dart:core-patch/dart:core/object_patch.dart:46)
E/flutter ( 3049): #1      _MyHomePageState.updateSnapshot (/data/user/0/com.yourcompany.merlin/cache/merlinCBXTTZ/merlin/lib/main.dart:45:61)
E/flutter ( 3049): <asynchronous suspension>
E/flutter ( 3049): #2      _MyHomePageState.initState (/data/user/0/com.yourcompany.merlin/cache/merlinCBXTTZ/merlin/lib/main.dart:55:10)
E/flutter ( 3049): #3      StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3655:14)
E/flutter ( 3049): #4      ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
E/flutter ( 3049): #5      Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
E/flutter ( 3049): #6      Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
E/flutter ( 3049): #7      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
E/flutter ( 3049): #8      Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
E/flutter ( 3049): #9      ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
E/flutter ( 3049): #10     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
E/flutter ( 3049): #11     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
E/flutter ( 3049): #12     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
E/flutter ( 3049): #13     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
E/flutter ( 3049): #14     Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
E/flutter ( 3049): #15     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
E/flutter ( 3049): #16     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
E/flutter ( 3049): #17     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
E/flutter ( 3049): #18     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
E/flutter ( 3049): #19     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4532:14)
E/flutter ( 3049): #20     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
E/flutter ( 3049): #21     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
E/flutter ( 3049): #22     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4532:14)
E/flutter ( 3049): #23     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
E/flutter ( 3049): #24     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
E/flutter ( 3049): #25     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
E/flutter ( 3049): #26     Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
E/flutter ( 3049): #27     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
E/flutter ( 3049): #28     StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3662:22)
E/flutter ( 3049): #29     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
E/flutter ( 3049): #30     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
E/flutter ( 3049): #31     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
E/flutter ( 3049): #32     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
E/flutter ( 3049): #33     Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
E/flutter ( 3049): #34     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
E/flutter ( 3049): #35     ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
E/flutter ( 3049): #36     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
E/flutter ( 3049): #37     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
E/flutter ( 3049): #38     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4532:14)
E/flutter ( 3049): #39     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
E/flutter ( 3049): #40     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
E/flutter ( 3049): #41     SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:4532:14)
E/flutter ( 3049): #42     Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
E/flutter ( 3049): #43     Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
E/flutter ( 3049): #44     ComponentElement.performRebuild (package:flutter/src/w
I/flutter ( 3049): #146    Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #147    ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #148    ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #149    Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #150    Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #151    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #152    Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #153    ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #154    ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #155    Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #156    Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #157    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #158    Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #159    ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #160    ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #161    Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #162    Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #163    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #164    Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #165    ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #166    StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3662:22)
I/flutter ( 3049): #167    ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #168    Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #169    Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #170    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #171    Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #172    ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #173    ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #174    Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #175    Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #176    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #177    Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #178    ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #179    StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3662:22)
I/flutter ( 3049): #180    ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #181    Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #182    Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #183    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #184    Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #185    ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #186    ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #187    Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #188    Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #189    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #190    Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #191    ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #192    ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #193    Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #194    Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #195    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #196    Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #197    ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #198    ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #199    Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #200    Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #201    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #202    Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #203    ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #204    StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3662:22)
I/flutter ( 3049): #205    ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #206    Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #207    Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #208    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #209    Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #210    ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #211    ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #212    Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #213    Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #214    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #215    Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #216    ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #217    StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3662:22)
I/flutter ( 3049): #218    ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #219    Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #220    Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #221    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3556:16)
I/flutter ( 3049): #222    Element.rebuild (package:flutter/src/widgets/framework.dart:3445:5)
I/flutter ( 3049): #223    ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3524:5)
I/flutter ( 3049): #224    ComponentElement.mount (package:flutter/src/widgets/framework.dart:3519:5)
I/flutter ( 3049): #225    Element.inflateWidget (package:flutter/src/widgets/framework.dart:2857:14)
I/flutter ( 3049): #226    Element.updateChild (package:flutter/src/widgets/framework.dart:2660:12)
I/flutter ( 3049): #227    RenderObjectToWidgetElement._rebuild (package:flutter/src/widgets/binding.dart:840:16)
I/flutter ( 3049): #228    RenderObjectToWidgetElement.mount (package:flutter/src/widgets/binding.dart:811:5)
I/flutter ( 3049): #229    RenderObjectToWidgetAdapter.attachToRenderTree.<anonymous closure> (package:flutter/src/widgets/binding.dart:757:17)
I/flutter ( 3049): #230    BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2173:19)
I/flutter ( 3049): #231    RenderObjectToWidgetAdapter.attachToRenderTree (package:flutter/src/widgets/binding.dart:756:13)
I/flutter ( 3049): #232    BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&RendererBinding&WidgetsBinding.attachRootWidget (package:flutter/src/widgets/binding.dart:647:7)
I/flutter ( 3049): #233    runApp (package:flutter/src/widgets/binding.dart:689:7)
I/flutter ( 3049): #234    main (/data/user/0/com.yourcompany.merlin/cache/merlinCBXTTZ/merlin/lib/main.dart:14:3)
I/flutter ( 3049): #235    _startIsolate.<anonymous closure> (dart:isolate-patch/dart:isolate/isolate_patch.dart:277)
I/flutter ( 3049): #236    _RawReceivePortImpl._handleMessage (dart:isolate-patch/dart:isolate/isolate_patch.dart:163)
I/flutter ( 3049): ════════════════════════════════════════════════════════════════════════════════════════════════════

@oneplusseven commented on Fri May 11 2018

Meanwhile, this video from Google I/O suggests other possibilities that may help you: https://youtu.be/RS36gBEp8OI.


@filiph commented on Thu Nov 08 2018

Our new site has https://flutter.io/docs/development/data-and-backend/state-mgmt. I will be working on this page and will update this bug as I go along.

Right now, the page is an amalgamation of links, going through different approaches — roughly from the simple to the complex. We'll be adding more guidance. It will always be "it depends" (on the project, on the team, on timeframe, etc.), but I think we can get to a point where starting with Flutter is much easier from the perspective state management.

milne-dev commented 5 years ago

Are there any plans on backing an official state management solution opposed to having several competing libraries/standards?

zoechi commented 5 years ago

There is no one-size-fits-all approach

pedromorgan commented 5 years ago

Ok so bumping into this snag on two project

Whats missing in the docs et in ecosystem is the techniques to do this, for muppets...

filiph commented 5 years ago

I'm making slow (but steady) progress on this.

Today, I landed the simplest possible example to github.com/flutter/samples — the Counter app, using ScopedModel. This should alleviate one of the most pressing issues: that there is no official sample that shows a Flutter app whose state is modified from "outside". Right now there's just the code (main.dart here). I'm working on an article that uses this example.

As @zoechi says, there is no one-size-fits-all, so please don't expect one single approach for state management. That said, we want to provide some starting points. ScopedModel has a good balance of easy-to-understand, easy-to-use, and stable.

pedromorgan commented 5 years ago

Adding a link to a blog https://medium.com/flutter-community/let-me-help-you-to-understand-and-choose-a-state-management-solution-for-your-app-9ffeac834ee3

One size fits all would be nice..

filiph commented 5 years ago

Docs have been slightly improved by https://github.com/flutter/website/pull/2332.

New pages start here: https://flutter.io/docs/development/data-and-backend/state-mgmt/intro

I would love your opinion on this. If you find that the current doc is still lacking (and it probably is), please don't hesitate to file a new bug with concrete suggestions. (And cc me.)

felangel commented 5 years ago

@filiph just curious what your thoughts are on https://github.com/felangel/bloc?

Docs: https://felangel.github.io/bloc

filiph commented 5 years ago

Hi @felangel, this looks really good!

My plan next is to invite package owners like you to contribute to the /options page. That way your work and the work of others is more visible. I do need to make sure the contributions don't get out of hand, though, so stay tuned for updates.