Objetivo do Projeto
Este projeto tem como finalidade implemenatr uma aplicação Flutter que utiliza RxDart e RxCommand para gerenciar estado de forma reativa. A interface deve incluir três campos de entrada de texto para números e um rótulo que exibe a soma em tempo real. Entradas não numéricas são consideradas como zero. Os valores iniciais dos campos são 1, 2 e 3, respectivamente.
Inicialização do Projeto
Após a instalação do Flutter, crie um novo projeto utilizando o comando:
flutter create meu_app_rx
Abra o diretório do projeto no Android Studio ou em um editor de sua preferência.
Configuração das Dependências
No arquivo pubspec.yaml, adicione as dependências necessárias para RxDart e RxCommand:
dependencies:
flutter:
sdk: flutter
rxdart: ^0.27.0
rx_command: ^6.0.0
Execute o comando flutter pub get para baixar os pacotes.
Implementação do Modelo de Dados
Crie um arquivo chamado reactive_model.dart na pasta lib com a seguinte estrutura:
import 'package:rx_command/rx_command.dart';
import 'package:rxdart/rxdart.dart';
class ReactiveModel {
final campo1 = RxCommand.createSync((String texto) => texto, initialLastResult: "1");
final campo2 = RxCommand.createSync((String texto) => texto, initialLastResult: "2");
final campo3 = RxCommand.createSync((String texto) => texto, initialLastResult: "3");
RxCommand<void string=""> total;
ReactiveModel() {
int converterParaInteiro(String valor) => int.tryParse(valor) ?? 0;
total = RxCommand.createFromStream((_) => CombineLatestStream.combine3(
campo1.startWith(campo1.lastResult),
campo2.startWith(campo2.lastResult),
campo3.startWith(campo3.lastResult),
(String a, String b, String c) {
int soma = converterParaInteiro(a) + converterParaInteiro(b) + converterParaInteiro(c);
return soma.toString();
}));
total(total.lastResult);
}
}</void>
Construção da Interface
No arquivo principal main.dart, configure a aplicação Flutter:
import 'package:flutter/material.dart';
import 'package:meu_app_rx/reactive_model.dart';
void main() {
runApp(Aplicativo());
}
class Aplicativo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Exemplo Reativo',
theme: ThemeData(
primarySwatch: Colors.green,
),
home: PaginaPrincipal(titulo: 'Página de Exemplo'),
);
}
}
class PaginaPrincipal extends StatefulWidget {
final String titulo;
PaginaPrincipal({Key chave, this.titulo}) : super(key: chave);
@override
_PaginaPrincipalState createState() => _PaginaPrincipalState();
}
class _PaginaPrincipalState extends State<paginaprincipal> {
final modelo = ReactiveModel();
TextEditingController controlador1;
TextEditingController controlador2;
TextEditingController controlador3;
_PaginaPrincipalState() {
controlador1 = TextEditingController(text: modelo.campo1.lastResult);
controlador2 = TextEditingController(text: modelo.campo2.lastResult);
controlador3 = TextEditingController(text: modelo.campo3.lastResult);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.titulo),
),
body: Center(
child: Container(
width: 200,
child: Table(
columnWidths: {0: FractionColumnWidth(.3)},
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
children: [
TableRow(children: [
Container(),
TextField(
controller: controlador1,
textAlign: TextAlign.center,
onChanged: modelo.campo1)
]),
TableRow(children: [
Center(child: Text("+")),
TextField(
controller: controlador2,
textAlign: TextAlign.center,
onChanged: modelo.campo2)
]),
TableRow(children: [
Center(child: Text("+")),
TextField(
controller: controlador3,
textAlign: TextAlign.center,
onChanged: modelo.campo3)
]),
TableRow(children: [
Center(child: Text("=")),
StreamBuilder(
stream: modelo.total,
builder: (context, snapshot) =>
Text(modelo.total.lastResult, textAlign: TextAlign.center),
),
]),
]),
),
),
);
}
}</paginaprincipal>