Skip to content

Commit fd46c2e

Browse files
committed
Refactor ListTileClicks listeners in input controls
Moved ListTileClicks notifier listeners from build methods to lifecycle methods (didChangeDependencies/initState/dispose) in checkbox, radio, and switch controls. This ensures listeners are properly registered and disposed, preventing duplicate listeners and potential memory leaks. Also, fixed SwitchControl to use activeThumbColor instead of activeColor. Fix #5627
1 parent 13cb882 commit fd46c2e

6 files changed

Lines changed: 57 additions & 28 deletions

File tree

packages/flet/lib/src/controls/checkbox.dart

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,20 @@ class _CheckboxControlState extends State<CheckboxControl> {
3434
_focusNode.addListener(_onFocusChange);
3535
}
3636

37+
@override
38+
void didChangeDependencies() {
39+
super.didChangeDependencies();
40+
ListTileClicks.of(context)?.notifier.addListener(_toggleValue);
41+
}
42+
3743
void _onFocusChange() {
3844
widget.control.triggerEvent(_focusNode.hasFocus ? "focus" : "blur");
3945
}
4046

4147
@override
4248
void dispose() {
4349
_focusNode.removeListener(_onFocusChange);
50+
ListTileClicks.of(context)?.notifier.removeListener(_toggleValue);
4451
_focusNode.dispose();
4552
super.dispose();
4653
}
@@ -98,11 +105,6 @@ class _CheckboxControlState extends State<CheckboxControl> {
98105
? (bool? value) => _onChange(value)
99106
: null);
100107

101-
// Add listener to ListTile clicks
102-
ListTileClicks.of(context)?.notifier.addListener(() {
103-
_toggleValue();
104-
});
105-
106108
Widget result = checkbox;
107109

108110
var labelStyle =

packages/flet/lib/src/controls/cupertino_checkbox.dart

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,20 @@ class _CheckboxControlState extends State<CupertinoCheckboxControl> {
3434
_focusNode.addListener(_onFocusChange);
3535
}
3636

37+
@override
38+
void didChangeDependencies() {
39+
super.didChangeDependencies();
40+
ListTileClicks.of(context)?.notifier.addListener(_toggleValue);
41+
}
42+
3743
void _onFocusChange() {
3844
widget.control.triggerEvent(_focusNode.hasFocus ? "focus" : "blur");
3945
}
4046

4147
@override
4248
void dispose() {
4349
_focusNode.removeListener(_onFocusChange);
50+
ListTileClicks.of(context)?.notifier.removeListener(_toggleValue);
4451
_focusNode.dispose();
4552
super.dispose();
4653
}
@@ -92,11 +99,6 @@ class _CheckboxControlState extends State<CupertinoCheckboxControl> {
9299
? (bool? value) => _onChange(value)
93100
: null);
94101

95-
// Add listener to ListTile clicks
96-
ListTileClicks.of(context)?.notifier.addListener(() {
97-
_toggleValue();
98-
});
99-
100102
Widget result = cupertinoCheckbox;
101103

102104
var labelStyle =

packages/flet/lib/src/controls/cupertino_radio.dart

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,32 @@ class _CupertinoRadioControlState extends State<CupertinoRadioControl>
3333
_focusNode.addListener(_onFocusChange);
3434
}
3535

36+
@override
37+
void didChangeDependencies() {
38+
super.didChangeDependencies();
39+
ListTileClicks.of(context)?.notifier.addListener(_toggleRadio);
40+
}
41+
3642
void _onFocusChange() {
3743
widget.control.triggerEvent(_focusNode.hasFocus ? "focus" : "blur");
3844
}
3945

4046
@override
4147
void dispose() {
4248
_focusNode.removeListener(_onFocusChange);
49+
ListTileClicks.of(context)?.notifier.removeListener(_toggleRadio);
4350
_focusNode.dispose();
4451
super.dispose();
4552
}
4653

54+
void _toggleRadio() {
55+
var radioGroup = RadioGroupProvider.of(context);
56+
if (radioGroup != null) {
57+
String value = widget.control.getString("value", "")!;
58+
_onChange(radioGroup, value);
59+
}
60+
}
61+
4762
void _onChange(Control radioGroup, String? value) {
4863
radioGroup.updateProperties({"value": value}, notify: true);
4964
radioGroup.triggerEvent("change", value);
@@ -62,7 +77,6 @@ class _CupertinoRadioControlState extends State<CupertinoRadioControl>
6277
debugPrint("CupertinoRadio build: ${widget.control.id}");
6378

6479
var radioGroup = RadioGroupProvider.of(context);
65-
6680
if (radioGroup == null) {
6781
return const ErrorControl(
6882
"CupertinoRadio must be enclosed within RadioGroup");
@@ -88,10 +102,6 @@ class _CupertinoRadioControlState extends State<CupertinoRadioControl>
88102
? (String? value) => _onChange(radioGroup, value)
89103
: null);
90104

91-
ListTileClicks.of(context)?.notifier.addListener(() {
92-
_onChange(radioGroup, value);
93-
});
94-
95105
Widget result = cupertinoRadio;
96106
if (label != "") {
97107
var labelWidget = widget.control.disabled

packages/flet/lib/src/controls/cupertino_switch.dart

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,21 @@ class _CupertinoSwitchControlState extends State<CupertinoSwitchControl> {
2929
super.initState();
3030
_focusNode = FocusNode();
3131
_focusNode.addListener(_onFocusChange);
32+
ListTileClicks.of(context)?.notifier.addListener(_toggleValue);
3233
}
3334

3435
@override
3536
void dispose() {
3637
_focusNode.removeListener(_onFocusChange);
38+
ListTileClicks.of(context)?.notifier.removeListener(_toggleValue);
3739
_focusNode.dispose();
3840
super.dispose();
3941
}
4042

43+
void _toggleValue() {
44+
_onChange(!_value);
45+
}
46+
4147
void _onChange(bool value) {
4248
_value = value;
4349
var props = {"value": value};
@@ -114,10 +120,6 @@ class _CupertinoSwitchControlState extends State<CupertinoSwitchControl> {
114120
}
115121
: null);
116122

117-
ListTileClicks.of(context)?.notifier.addListener(() {
118-
_onChange(!_value);
119-
});
120-
121123
Widget result = swtch;
122124
if (label != "") {
123125
var labelWidget = widget.control.disabled

packages/flet/lib/src/controls/radio.dart

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,32 @@ class _RadioControlState extends State<RadioControl> {
3232
_focusNode.addListener(_onFocusChange);
3333
}
3434

35+
@override
36+
void didChangeDependencies() {
37+
super.didChangeDependencies();
38+
ListTileClicks.of(context)?.notifier.addListener(_toggleRadio);
39+
}
40+
3541
void _onFocusChange() {
3642
widget.control.triggerEvent(_focusNode.hasFocus ? "focus" : "blur");
3743
}
3844

3945
@override
4046
void dispose() {
4147
_focusNode.removeListener(_onFocusChange);
48+
ListTileClicks.of(context)?.notifier.removeListener(_toggleRadio);
4249
_focusNode.dispose();
4350
super.dispose();
4451
}
4552

53+
void _toggleRadio() {
54+
var radioGroup = RadioGroupProvider.of(context);
55+
if (radioGroup != null) {
56+
String value = widget.control.getString("value", "")!;
57+
_onChange(radioGroup, value);
58+
}
59+
}
60+
4661
void _onChange(Control radioGroup, String? value) {
4762
radioGroup.updateProperties({"value": value}, notify: true);
4863
radioGroup.triggerEvent("change", value);
@@ -95,10 +110,6 @@ class _RadioControlState extends State<RadioControl> {
95110
? (String? value) => _onChange(radioGroup, value)
96111
: null);
97112

98-
ListTileClicks.of(context)?.notifier.addListener(() {
99-
_onChange(radioGroup, value);
100-
});
101-
102113
Widget result = radio;
103114
if (label != "") {
104115
var labelWidget = widget.control.disabled

packages/flet/lib/src/controls/switch.dart

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,21 @@ class _SwitchControlState extends State<SwitchControl> {
3131
super.initState();
3232
_focusNode = FocusNode();
3333
_focusNode.addListener(_onFocusChange);
34+
ListTileClicks.of(context)?.notifier.addListener(_toggleValue);
3435
}
3536

3637
@override
3738
void dispose() {
3839
_focusNode.removeListener(_onFocusChange);
40+
ListTileClicks.of(context)?.notifier.removeListener(_toggleValue);
3941
_focusNode.dispose();
4042
super.dispose();
4143
}
4244

45+
void _toggleValue() {
46+
_onChange(!_value);
47+
}
48+
4349
void _onChange(bool value) {
4450
_value = value;
4551
var props = {"value": value};
@@ -78,7 +84,7 @@ class _SwitchControlState extends State<SwitchControl> {
7884
autofocus: autofocus,
7985
padding: widget.control.getPadding("padding"),
8086
focusNode: _focusNode,
81-
activeColor: widget.control.getColor("active_color", context),
87+
activeThumbColor: widget.control.getColor("active_color", context),
8288
activeTrackColor:
8389
widget.control.getColor("active_track_color", context),
8490
inactiveThumbColor:
@@ -105,10 +111,6 @@ class _SwitchControlState extends State<SwitchControl> {
105111
}
106112
: null);
107113

108-
ListTileClicks.of(context)?.notifier.addListener(() {
109-
_onChange(!_value);
110-
});
111-
112114
Widget result = s;
113115

114116
if (label is Control || (label is String)) {

0 commit comments

Comments
 (0)