ReactiveX 学习笔记(35)使用 RxDart + RxCommand 进行 GUI 编程

课题

  1. 程序界面由3个文本编辑框和1个文本标签组成。
  2. 要求文本标签实时显示3个文本编辑框所输入的数字之和。
  3. 文本编辑框输入的不是合法数字时,将其值视为0。
  4. 3个文本编辑框的初值分别为1,2,3。

创建工程

Flutter 安装完毕之后执行以下命令创建工程

flutter create rx_example

打开 Android Studio,File / Open...
选择 rx_example 文件夹以打开 Flutter 工程。

添加依赖

打开 pubspec.yaml 文件,在 dependencies: 下添加对 RxDart 和 RxCommand 的依赖

dependencies:
  flutter:
    sdk: flutter
  rxdart: 0.25.0
  rx_command: ^5.3.0

点击 Pub get 下载所依赖的包

ViewModel

在 lib 文件夹下添加 rx_example_viewmodel.dart 文件,内容如下

import 'package:rx_command/rx_command.dart';
import 'package:rxdart/rxdart.dart';

class RxExampleModel {
  final number1 = RxCommand.createSync((String v) => v, initialLastResult: "1");
  final number2 = RxCommand.createSync((String v) => v, initialLastResult: "2");
  final number3 = RxCommand.createSync((String v) => v, initialLastResult: "3");
  RxCommand<void, String> result;

  RxExampleModel() {
    int f(String s) => int.tryParse(s) ?? 0;
    result = RxCommand.createFromStream((_) => CombineLatestStream.combine3(
        number1.startWith(number1.lastResult),
        number2.startWith(number2.lastResult),
        number3.startWith(number3.lastResult),
        (String a, String b, String c) => (f(a) + f(b) + f(c)).toString()));
    result(result.lastResult);
  }
}

Main

最后打开 main.dart,将内容改为

import 'package:flutter/material.dart';
import 'package:rx_example/rx_example_viewmodel.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: RxExamplePage(title: 'Rx Example Page'),
    );
  }
}

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

  final String title;

  @override
  _RxExamplePageState createState() => _RxExamplePageState();
}

class _RxExamplePageState extends State<RxExamplePage> {
  final vm = RxExampleModel();
  TextEditingController number1Ctrl;
  TextEditingController number2Ctrl;
  TextEditingController number3Ctrl;
  final resultCtrl = TextEditingController();

  _RxExamplePageState() {
    number1Ctrl = TextEditingController(text: vm.number1.lastResult);
    number2Ctrl = TextEditingController(text: vm.number2.lastResult);
    number3Ctrl = TextEditingController(text: vm.number3.lastResult);
    vm.result.listen((v) => resultCtrl.text = v);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Container(
            width: 150,
            child: Table(
                columnWidths: {0: FractionColumnWidth(.2)},
                defaultVerticalAlignment: TableCellVerticalAlignment.middle,
                children: [
                  TableRow(children: [
                    Container(),
                    TextField(
                        controller: number1Ctrl,
                        textAlign: TextAlign.end,
                        onChanged: vm.number1)
                  ]),
                  TableRow(children: [
                    Container(),
                    TextField(
                        controller: number2Ctrl,
                        textAlign: TextAlign.end,
                        onChanged: vm.number2)
                  ]),
                  TableRow(children: [
                    Center(child: Text("+")),
                    TextField(
                        controller: number3Ctrl,
                        textAlign: TextAlign.end,
                        onChanged: vm.number3)
                  ]),
                  TableRow(children: [
                    Center(child: Text("=")),
                    TextField(controller: resultCtrl, textAlign: TextAlign.end)
                  ])
                ])),
      ),
    );
  }
}
上一篇:ESP8266-NODEMCU


下一篇:ubuntu 安装AMD显卡的OpenCL支持