Использование виджетов с отслеживанием состояния, приводящих к отображению устаревших виджетов
У меня есть пользовательский интерфейс, который получает обновления текста по сети.Когда приходит обновление, я хочу сначала показать его красным, а затем постепенно поменять его на черный, поскольку возраст сообщения увеличивается.Если новое сообщение поступает из того же источника, я хотел заменить текст старого сообщения новым сообщением, а затем снова перевести текст с красного на черный.
Когда я использую Statefulвиджет с RestartableTimer, и я сначала запускаю свой интерфейс, кажется, все работает нормально.Однако, как только из определенного источника приходит сообщение second , вот где что-то ломается.Если я использую обычный текст () для отображения нового сообщения, оно работает просто отлично.Но если я использую виджет Stateful для отображения текста и постепенно исчезает с красного на черный, пользовательский интерфейс остается устаревшим, и никакое количество обновлений, похоже, не помогает.
Моя иерархия (с удаленными компонентами макета) выглядитнапример:
Stateful Container for different sources
|
List View
|
+--- Stateless Custom Widget
|
+-- Stateless Text (displays the source)
|
+-- Stateful Custom Text class
<repeated for each source>
Если я заменю свой пользовательский класс обычным текстом (), то текст внезапно обновится очень хорошо (но цвет не исчезнет).
Пользовательский виджет без сохранения состояния
Widget _CreateDataTable() {
const Color start_color = Colors.red;
const Color end_color = Colors.black;
const Duration fade_len = Duration(seconds: 10);
var read_time = DateTime.fromMillisecondsSinceEpoch(
_data.data.timeSeconds * 1000,
isUtc: true);
String date_text = read_time.toLocal().toString();
List<String> labels = ["Temperature", "Humidity", "RSSI", "Last Reading"];
List<Widget> data = [
Text(_data.data.temperature.toStringAsFixed(2) + " C"),
Text(_data.data.humidity.toStringAsFixed(2) + "%"),
Text(_data.rssi.toString() + " dB"),
FlashText(date_text, start_color, end_color, read_time, fade_len),
// Text(date_text),
//
// IF I COMMENT OUT FlashText AND UNCOMMENT Text, EVERYTHING
// WORKS FINE. IF I KEEP IT AS IS, I ONLY SEE THE FIRST EVER
// MESSAGE AND NEW MESSAGES, WHICH I CAN CONFIRM RECEIVING VIA
// debugPrint, ARE SEEMINGLY IGNORED.
];
var rows = List<Row>();
for (int i = 0; i < labels.length; ++i) {
rows.add(Row(children: [
IntrinsicWidth(child: SizedBox(width: 10.0)),
IntrinsicWidth(child: Text(labels[i] + ":")),
IntrinsicWidth(child: data[i]),
Expanded(child: SizedBox()),
]));
}
return Column(children: rows);
Пользовательский виджет с сохранением состояния
class FlashText extends StatefulWidget {
final Color _color0;
final Color _color1;
final DateTime _start;
final Duration _duration;
final String _text;
FlashText(
this._text, this._color0, this._color1, this._start, this._duration);
@override
_FlashTextState createState() {
debugPrint("Creating state for $_text - $_start");
return _FlashTextState(_text, _color0, _color1, _start, _duration);
}
}
class _FlashTextState extends State<FlashText> {
Color _color0;
Color _color1;
DateTime _start;
Duration _duration;
String _text;
Animation<double> _animation;
AnimationController _controller;
_FlashTextState(
this._text, this._color0, this._color1, this._start, this._duration);
@override
Widget build(BuildContext ctx) {
return Text(_text,
style: TextStyle(color: Color.lerp(_color0, _color1, _GetT())));
}
@override
void initState() {
super.initState();
RestartableTimer(_duration ~/ 30, _Update);
}
double _GetT() {
DateTime now = DateTime.now().toUtc();
return min(1, max(0, now.difference(_start).inMilliseconds /
_duration.inMilliseconds.toDouble()));
}
void _Update() {
if (_GetT() < 1.0) RestartableTimer(_duration ~/ 30, _Update);
}
}