6. Flutter: Gerencia de Estado: Streams

Streams são como se fossem fluxos assincronos, fornecem uma sequência assíncrona de dados.

6. Flutter: Gerencia de Estado: Streams

Quais os objetivos de um Stream?

  1. Streams fornecem uma sequência assíncrona de dados;
  2. Sequências de dados incluem eventos gerados pelo usuário e leitura de dados de arquivos;
  3. Você pode processar um stream usando await for ou listen() a partir da API Stream;
  4. Os streams fornecem uma maneira de responder a erros;
  5. Existem dois tipos de streams: single subscription(assinatura única) ou broadcast (múltiplas assinaturas);

Iremos começar por um StatefulWidget, pois toda vez que usamos uma stream, precisamos chamar o dispose() para retirá-la da memória.

Para iniciar a nossa stream, precisamos criar um controlador:

import 'dart:async';

class Controller {
  // criar controlador
  final _controller = StreamController();
}

Toda vez que criamos uma stream, precisamos dar o dispose dela quando sairmos da página:

import 'dart:async';

class Controller {
  // criar controlador
  final _controller = StreamController();

  void dispose() {
    _controller.close();
  }
}

Criando nosso estado:

class StateManager {
  String nome;

  StateManager({
    this.nome,
  });
}

Tipando nossa stream e criando uma ação:

import 'dart:async';

import 'state.dart';

class Controller {
  // criar controlador
  final _controller = StreamController();

  void alterarNome() {}

  void dispose() {
    _controller.close();
  }
}

Criando nossa acesso ao stream com Getters e criando um construtor para setar nosso estado inicial:

import 'dart:async';

import 'state.dart';

class Controller {
  // criar controlador
  final _controller = StreamController();

  // criando um get
  Stream get outAtualizarNome => _controller.stream;

  Controller() {
    // add estado dentro do controller, estado inicial
    _controller.add(
      StateManager(
        nome: "FlutterBRasil",
      ),
    );
  }

  void alterarNome(String value) {
    _controller.add(
      StateManager(
        nome: value,
      ),
    );
  }

  void dispose() {
    _controller.close();
  }
}

Vamos agora instanciar nosso controlador na nossa page e aproveitar e dar dispose():

class _MyAppState extends State {
  final Controller _controller = Controller();

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          children: [
            Text("Nome"),
            RaisedButton(
              onPressed: () => _controller.alterarNome("BRasil"),
              child: Text("Alterar Nome"),
            )
          ],
        ),
      ),
    );
  }
}

Agora, para recuperar os nossos dados, das streams, utilizaremos o StreamBuilder():

class _MyAppState extends State {
  final Controller _controller = Controller();

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
    
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          children: [
            StreamBuilder(
              stream: _controller.outAtualizarNome,
              builder: (_, snapshot) {
                return Text("${snapshot.data.nome}");
              }
            ),
            RaisedButton(
              onPressed: () => _controller.alterarNome(),
              child: Text("Alterar Nome"),
            )
          ],
        ),
      ),
    );
  }
}

Pronto, tudo funcionando. Espero que tenham gostado.