Solucionado (ver solução)
Solucionado
(ver solução)
4
respostas

Adicionando na tela

Meu código não adiciona na tela, porque? Criei um repositório no github, porque não entendo porque ele não carrega os novos dados na tela. Só no terminal.

https://github.com/gisesonia/bytebankalura

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

void main() => runApp(BytebankApp());

class BytebankApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: ListaTransferencias(),
      ),
    );
  }
}

class FormularioTransferencia extends StatelessWidget {

  final TextEditingController _controladorCampoNumeroConta = TextEditingController();
  final TextEditingController _controladorCampoValor = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text('Criando Transferência'),),
        body: Column(
          children: [
            Editor(controlador: _controladorCampoNumeroConta,
                rotulo:'Número da conta',
                dica:'000'
            ),
            Editor(
                controlador: _controladorCampoValor,
                rotulo: 'Valor',
                dica: '0.00',
                icone: Icons.monetization_on),
            RaisedButton(
              child: Text('confirmar'),
              onPressed: () {
                _criaTransferencia(context);
              },
            ),
          ],
        ));
  }

  void _criaTransferencia(BuildContext context) {
    final int numeroConta = int.tryParse(_controladorCampoNumeroConta.text);
    final double valor = double.tryParse(_controladorCampoValor.text);
    if(numeroConta != null && valor != null) {
     final transferenciaCriada = Transferencia(valor, numeroConta);
     debugPrint('Criando transferência');
     debugPrint('$transferenciaCriada');
     Navigator.pop(context, transferenciaCriada);
    }
  }
}

class Editor extends StatelessWidget {

  final TextEditingController controlador;
  final String rotulo;
  final String dica;
  final IconData icone;

  Editor({this.controlador, this.rotulo, this.dica, this.icone});

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: TextField(
        controller: controlador,
        style: TextStyle(
            fontSize: 24.0
        ),
        decoration: InputDecoration(
            icon: icone != null ? Icon(icone) : null,
            labelText: rotulo,
            hintText: dica
        ),
        keyboardType: TextInputType.number,
      ),
    );
  }
}

class ListaTransferencias extends StatefulWidget {//mudei aqui
  final List<Transferencia> _transferencias = List();

  @override
  State<StatefulWidget> createState() {
    return ListaTransferenciasState();
  }
}

class ListaTransferenciasState extends State<ListaTransferencias> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Transferências'),
      ),
      body: ListView.builder(
        itemCount: widget._transferencias.length,
        itemBuilder: (context, indice) {
          final transferencia = widget._transferencias[indice];
          return ItemTransferencia(transferencia);
        },
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add), onPressed: (){
        final Future<Transferencia> future = Navigator.push(context, MaterialPageRoute(builder: (context){
          return FormularioTransferencia();
        }));
        future.then((transferenciaRecebida) {
          debugPrint('chegou no then do future');
          debugPrint('$transferenciaRecebida');
          widget._transferencias.add(transferenciaRecebida);// isso que deveria mostrar na tela?
        });
      },
      ),
    );
  }
}

class ItemTransferencia extends StatelessWidget {

  final Transferencia _transferencia;

  ItemTransferencia(this._transferencia);

  @override
  Widget build(BuildContext context) {
    return Card(
        child: ListTile(
          leading: Icon(Icons.monetization_on),
          title: Text(_transferencia.valor.toString()),
          subtitle: Text(_transferencia.numeroConta.toString()),
        ));
  }
}

class Transferencia {
  final double valor;
  final int numeroConta;

  Transferencia(this.valor, this.numeroConta);

  @override
  String toString() {
    return 'Transferencia{valor: $valor, numeroConta: $numeroConta}';
  }
}
4 respostas

Você terá que usar a função setState para que o Flutter saiba que o valor foi atualizado e portanto possa chamar o build novamente.

setState(() {
          widget._transferencias.add(transferenciaRecebida);
});

É necessário adicionar esta informação num bloco de informações antes da transcrição da atividade "Implementando o StatefulWidget". O professor não menciona o setState e o comportamento da aplicação não se apresenta como descrito por ele.

É realmente, procurei e revisei tudo, não tem isso e onde no código eu tenho que colocar isso? Tem mais pra frente no curso? Coloquei dessa forma e ficou vermelho. Uma coisa que ficou meio sem explicação foi também a ordem de execução das funções, me perdi um pouco no fluxo dos dados. Por isso não estava sabendo resolver, essa função está ligada a que? Eu estava aprendendo react native e isso lembrou bem o state do react.

Isso funcionou, mas não sei se é o correto. O que é esse future? É opcional?

 floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add), onPressed: () {
        final Future<Transferencia> future = Navigator.push(context, MaterialPageRoute(builder: (context) {
          return FormularioTransferencia();
        }));
        future.then((transferenciaRecebida) {

          setState(() {
            widget._transferencias.add(transferenciaRecebida);
          });
        });
      },),

Eu vi exemplo sem usar isso, fui buscar, porque procurando só statefulWidget não estava conseguindo encontrar a solução e nesse exemplo explica exatamente que o setState atualiza o estado. Aula widget com estado https://classroom.udacity.com/courses/ud905/

solução!

Sim, ele vai mencionar o setState na parte de correção de bugs.

O future é opcional e funciona como promises no javascript. O then é responsável por esperar você retornar à página para continuar a rodar o código. Vamos analisar esse trecho do código:

final Future<Transferencia> future = Navigator.push(context, MaterialPageRoute(builder: (context) {
          return FormularioTransferencia();
        }));
        future.then((transferenciaRecebida) {
          setState(() {
            widget._transferencias.add(transferenciaRecebida);
          });

Na primeira linha ele vai estar te mandando para a tela do formulário de transferência. Quando você entra nessa página, o código de baixo continuaria rodando e não teria como você pegar o valor do que você enviou no formulário. Então o then vai servir para esperar ele retornar um resultado. O que está como parâmetro do callback do then (transferenciaRecebida) é onde você vai receber os dados do formulário e dentro das chaves é onde você vai usar esse dado.

"Ok, mas eu preciso do future?"

Não, isso só serve pra deixar o código mais legível. Você também poderia escrever assim:

Navigator.push(context, MaterialPageRoute(builder: (context) {
          return FormularioTransferencia();
        }))
.then((transferenciaRecebida) {
          setState(() {
            widget._transferencias.add(transferenciaRecebida);
          });