对 「3.2.2 父Widget管理子Widget的状态 」的个人建议
您好,首先感谢写出这么好的文章。下面是我的一点小建议: 「3.2.2 父Widget管理子Widget的状态 」中,阐述得很好,但是在代码示例中却用
final ValueChanged
来做一个回调,这样代码看起来还是又「子widget」来定义了状态。相当于「子Widget」自己通过回调告诉了「父Widget」,“我的状态将会改变为 true”,然后「父Widget」只是调用一个 setState而已。我在阅读这一段的时候感觉有点别扭。 我的理解是「子Widget」只应该知道自己被 tap 了一下,然后「父Widget」来做状态的逻辑处理。代码为:
class TapBoxB extends StatelessWidget{
final bool active ; final GestureTapCallback onTapped;
TapBoxB({Key key,this.active,@required this.onTapped}):super(key:key);
@override Widget build(BuildContext context) {
return GestureDetector( onTap: onTapped, child:// 省略 ); } }
可以举一个场景来阐述,我需要「连点3下TapBoxB」才能把 「TapBoxB」激活,激活后只需tap一次就可以取消激活。讲道理如果是「父Widget」来控制状态的话,TapBoxB应该是不需要改动的。只需要改动 「父Widget」就OK了:
class _TapBoxBWidgetState extends State<TapBoxBParent>{
bool _active = false; int tapCount = 0;
void _handleTap(){ if(_active) { setState(() { _active = false; }); tapCount = 0; return; } if(++tapCount>=3) { setState(() { _active = true; }); } } @override Widget build(BuildContext context) { return new TapBoxB(active: _active,onTapped: _handleTap); } }
当然你之前的写法也可以实现,但是代码看起来很奇怪,「子Widget」不管理自己的状态,那怎么会知道自己 onChanged(active)了呢? 我理解不对的地方,请多多指教。
这个例子中谁来管理状态就是指谁来保存active的状态,子组件的active属性只是作为了接收父组件传值的参数,内部并没有来维护active的变动情况,子组件点击时新的状态就自然是!active,由于是父组件管理的active状态,所以父组件有权决定要不要用最新的状态来重新构建子组件(调用setState), 如果父组件不需要重新构建子组件,那么即使子组件点多少次,状态都不会变。
感谢。
@wendux 你好
刚好看到这一节,使用这一节的源码,运行报错,不知道是什么原因
I/flutter ( 2285): ══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
I/flutter ( 2285): The following NoSuchMethodError was thrown while handling a gesture:
I/flutter ( 2285): The method 'call' was called on null.
I/flutter ( 2285): Receiver: null
I/flutter ( 2285): Tried calling: call(true)
I/flutter ( 2285): When the exception was thrown, this was the stack:
I/flutter ( 2285): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
I/flutter ( 2285): #1 TapboxB._handleTap (package:first_flutter_app/TapboxB.dart:41:5)
I/flutter ( 2285): #2 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:182:24)
I/flutter ( 2285): #3 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:486:11)
I/flutter ( 2285): #4 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:264:5)
I/flutter ( 2285): #5 BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:199:7)
I/flutter ( 2285): #6 PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:470:9)
I/flutter ( 2285): #7 PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:76:12)
I/flutter ( 2285): #8 PointerRouter._dispatchEventToRoutes.
版本信息如下: ➜ first_flutter_app flutter --version Flutter 1.14.6 • channel unknown • unknown source Framework • revision fabeb2a16f (5 个月前) • 2020-01-28 07:56:51 -0800 Engine • revision c4229bfbba Tools • Dart 2.8.0 (build 2.8.0-dev.5.0 fc3af737c7)