
                            
                            因收到Google相关通知，网站将会择期关闭。相关通知内容
                            
                            
                            09 校验结果与提示信息
                            1. 需求中的状态数据分析

在上一篇中，已经准备好了数据和界面。本篇将介绍比较结果的校验，以及展示用户输入值和随机目标值的大小信息。点击确定时，可能的结果有 3 中，如下所示：





如下所示，是点击确定时不同情况下期望的界面效果；也就是说，界面的展现需要随着用户交互而变化。所以在当前需求之下，需要引入新的状态数据，用于控制界面的表现。




大了
小了
相等











这个状态数据将用于表示校验结果，该用什么类型呢？首先要明确一点：比较结果有三种情况: 大了、小了、相等 。其实只要某种数据类型包含三个值，都可以用于表示校验状态，只要逻辑正确即可，比如:

int 型: 
0: 大了
1: 小了
2: 相等

String 型: 
'big': 大了
'small': 小了
'equal': 相等


但如果用 int 或 String 表示，首先必须提前做出规定。而对于不了解规定的人，在阅读时会增加理解的难度。如果这种类似的规定场景在一个项目里经常出现，就是一个个雷点，迟早会爆炸。其实 bool 类型的出现，就是为了避免用 0 和 1 整数来表示真假，带来语义上的难以理解。

能且仅能是一种语法上的约束，可以在根源上杜绝一些可能发生的错误。那问一个问题，什么类型有且仅有 3 个值？很多人会说 枚举，这确实可以，不过稍显麻烦。这里想用 bool?来表示三态，它有如下三个值：

null: 相等
true: 大了
false: 小了


分析完后，现在 _GuessPageState 里定义为变量 _isBig 作为状态数据，控制校验结果。默认为 null ：

bool? _isBig;




2. 校验逻辑与状态数据的维护

校验逻辑算是比较简单的，对状态数据的维护可以称之为 业务逻辑，校验逻辑将在 _onCheck 回调中进行。上篇说过，这里可以得到目标值和输入值，输入值可以通过 int.tryParse 吧字符串转为整型。
有些小细节要注意一下：如果 _guessing 为 false ，表示游戏未开始；或输入的不是整数，此时应该不做响应，直接返回即可。

void _onCheck() {
  print("=====Check:目标数值:$_value=====${_guessCtrl.text}============");
  
  int? guessValue = int.tryParse(_guessCtrl.text);
  // 游戏未开始，或者输入非整数，无视
  if (!_guessing || guessValue == null) return;
  
  //猜对了
  if (guessValue == _value) {
    setState(() {
      _isBig = null;
      _guessing = false;
    });
    return;
  }
  
  // 猜错了
  setState(() {
    _isBig = guessValue > _value;
  });
}


如果猜对了，表示游戏结束，将 _guessing 置为 true、_isBig 置为 null ; 如果猜错了，通过 guessValue 和 _value 的比较结果，为 _isBig 赋值。这就是对状态数据的维护过程。





3. 状态数据与界面构建逻辑

状态数据以及维护完毕，下面来看一下最后一步：使用 _isBig 状态控制界面的呈现。从最终效果，可以推断出_isBig 对界面的功效：




大了
小了
相等













背景的色框提示，只有在大了或小了时才会出现，也就是说当 _isBig != null 时才会出现，对应下面代码的 69 行 。
大了和小了是互斥的，不会同时出现，通过 Spacer 进行占位，大了时占下半；小了时占上半。





注: isBig! 是空安全的语法，如果一个可空对象 100% 确定非 null。可以通过 对象名! 表示 非空对象。 由于上面 if(_isBig) 才会走下方逻辑，所以使用处 100% 非空。




4.本章小结

到这里，猜数字简单版本就已经完成了。当前代码提交位置: guess_page.dart 你可以随机生成数字，在输入框中猜测数字，并校验猜测的值，给出提示。虽然是个小案例，但相比于计数器来说复杂了一些，额外维护了几个状态数据，界面布局上也更加复杂。是一个初学者进一步了解 Flutter 的好案例，把它吃透，会对你受益匪浅。

虽然现在可以完成猜数字需求，但是还有一点缺陷。比如当校验 小了， 下次校验还小时，由于 _isBig 的状态类没变，提示界面就没有任何变化(下左图)。如果用户的一个操作得不到反馈，体感上会觉得可能没点好；此时给予用户视觉上的反馈就会有比较好的体验，比如加一个动画效果(下左图)：




无动画
有动画











                        
                        
                            