When I make a ListView with an array of stateless widgets I get no errors, everything works perfectly. However when I put Stateful widgets into the array and rerender the widget by scrolling it so it ends outside of the view then I get errors.
I tried it on ListView and ListView.builder and there seems to be no difference. I thought the problem was with the text so I tried to remove all Text constructors but there was no difference. The widget does initialize and dispose but does not reinitialize.
class CustomSettingsScreen extends StatefulWidget {
static const String routeName = "/settings";
@override
CustomSettingsScreenState createState() =>CustomSettingsScreenState();
}
class CustomSettingsScreenState extends State<CustomSettingsScreen> {
@override
void initState() {
super.initState();
}
final listElements = {
Divider(height: 500),
VibrateStartRecordingEnablePreference(
preferenceKey: PreferenceKeys.keyVibrateStartRecordingEnable,
),
Divider(height: 500),
Divider(height: 500),
Divider(height: 500),
Divider(height: 500),
};
};
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Settings"),
),
body: ListView.builder(
itemCount: listElements.length,
itemBuilder: (BuildContext context, int index) {
return listElements.elementAt(index);
},
),);
}
}
class VibrateStartRecordingEnablePreference extends StatefulWidget {
VibrateStartRecordingEnablePreference({
Key key,
@required this.preferenceKey,
});
final preferenceKey;
final _VibrateStartRecordingEnablePreferenceState
_vibrateStartRecordingEnablePreferenceState =
new _VibrateStartRecordingEnablePreferenceState();
@override
_VibrateStartRecordingEnablePreferenceState createState() =>
_vibrateStartRecordingEnablePreferenceState;
}
class _VibrateStartRecordingEnablePreferenceState extends State<VibrateStartRecordingEnablePreference> {
String _title = "Vibrate at the start of recording";
String _subtitleOn = "Vibrates once upon start of recording";
String _subtitleOff = "Will not vibrate at start";
bool _value = true;
String _getSubtitle() {
if (_value)
return _subtitleOn;
else
return _subtitleOff;
}
void _updateValue(bool value) {
Settings().save(widget.preferenceKey, value);
setState(() {
_value = value;
});
}
@override
void initState() {
//Update the values and text
Settings().getBool(widget.preferenceKey, true).then((value) {
setState(() {
_value = value;
});
});
super.initState();
}
@override
Widget build(BuildContext context) {
return new SwitchListTile(
secondary: const Icon(Icons.vibration),
title: Text("$_title"),
subtitle: Text(_getSubtitle()),
value: _value,
onChanged: (value) {
_updateValue(value);
},
);
}
}
The error in debugger
The following assertion was thrown building NotificationListener<KeepAliveNotification>: 'package:flutter/src/widgets/framework.dart': Failed assertion: line 4006 pos
12: '_state._widget == null': is not true.
Here is a video of what is happening. https://webm.red/6ZTH
_vibrateStartRecordingEnablePreferenceState
is stored inside VibrateStartRecordingEnablePreference
which is wrong.
Framework tries to attach state instance to widget, but state is already attached to one. So it leads to exception.
You have to return a new instance of state every time when createState()
is called in StatefulWidget