From a603a178757f56ded94cde36394585830c4e0930 Mon Sep 17 00:00:00 2001 From: Taha Tesser Date: Fri, 16 Feb 2024 09:43:50 +0200 Subject: [PATCH] Update `MaterialStatesController` docs for calling `setState` in a listener (#143453) fixes [Calling `setState` in a `MaterialStatesController` listener and `MaterialStateController.update` causes Exception](https://github.com/flutter/flutter/issues/138986) ### Description `MaterialStatesController` listener calls `setState` during build when `MaterialStatesController.update` listener calls `notifyListeners`. I tried fixing this issue by putting `notifyListeners` in a post-frame callback. However, this breaks existing customer tests (particularly super editor tests). A safer approach would be to document that the listener's `setState` call should be in a post-frame callback to delay it and not call this during the build phase triggered by the `MaterialStatesController.update` in the widgets such as InkWell or buttons. --- packages/flutter/lib/src/material/material_state.dart | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/flutter/lib/src/material/material_state.dart b/packages/flutter/lib/src/material/material_state.dart index c1d23d622c7b..78f7ba3bffb2 100644 --- a/packages/flutter/lib/src/material/material_state.dart +++ b/packages/flutter/lib/src/material/material_state.dart @@ -760,6 +760,14 @@ class MaterialStatePropertyAll implements MaterialStateProperty { /// [MaterialState.focused] to its controller. When the widget gains the /// or loses the focus it will [update] its controller's [value] and /// notify listeners of the change. +/// +/// When calling `setState` in a [MaterialStatesController] listener, use the +/// [SchedulerBinding.addPostFrameCallback] to delay the call to `setState` after +/// the frame has been rendered. It's generally prudent to use the +/// [SchedulerBinding.addPostFrameCallback] because some of the widgets that +/// depend on [MaterialStatesController] may call [update] in their build method. +/// In such cases, listener's that call `setState` - during the build phase - will cause +/// an error. class MaterialStatesController extends ValueNotifier> { /// Creates a MaterialStatesController. MaterialStatesController([Set? value]) : super({...?value});