Mix of Stateful and Stateless flutter UI not getting updated

Multi tool use
Multi tool use












0















Using stateful widgets causing stale widgets to be displayed



I have a UI that receives update text updates over the network. When an update comes in, I wish to first show it in red, then have it slowly fade to black as the message's age increases. If a new message comes in from the same source, I wanted to replace the text of the old message with the new message, then have the text fade from red to black all over again.



When I use a Stateful widget with a RestartableTimer, and I first start my UI, everything seems to work fine. However, as soon as the second message comes in from a particular source, that's where things break. If I use a plain Text() to display the new message, it works just fine. But if I use a Stateful widget to display the text and fade from red to black, the UI remains stale and no amount of updating seems to do the trick.



My hierarchy (with layout-specific stuff removed) looks like:



Stateful Container for different sources
|
List View
|
+--- Stateless Custom Widget
|
+-- Stateless Text (displays the source)
|
+-- Stateful Custom Text class
<repeated for each source>


If I replace my custom class with a plain Text(), then suddenly the text updates just fine (but there's no fading of color).



Stateless Custom Widget



  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);


Stateful Custom Widget



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);
}
}









share|improve this question



























    0















    Using stateful widgets causing stale widgets to be displayed



    I have a UI that receives update text updates over the network. When an update comes in, I wish to first show it in red, then have it slowly fade to black as the message's age increases. If a new message comes in from the same source, I wanted to replace the text of the old message with the new message, then have the text fade from red to black all over again.



    When I use a Stateful widget with a RestartableTimer, and I first start my UI, everything seems to work fine. However, as soon as the second message comes in from a particular source, that's where things break. If I use a plain Text() to display the new message, it works just fine. But if I use a Stateful widget to display the text and fade from red to black, the UI remains stale and no amount of updating seems to do the trick.



    My hierarchy (with layout-specific stuff removed) looks like:



    Stateful Container for different sources
    |
    List View
    |
    +--- Stateless Custom Widget
    |
    +-- Stateless Text (displays the source)
    |
    +-- Stateful Custom Text class
    <repeated for each source>


    If I replace my custom class with a plain Text(), then suddenly the text updates just fine (but there's no fading of color).



    Stateless Custom Widget



      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);


    Stateful Custom Widget



    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);
    }
    }









    share|improve this question

























      0












      0








      0








      Using stateful widgets causing stale widgets to be displayed



      I have a UI that receives update text updates over the network. When an update comes in, I wish to first show it in red, then have it slowly fade to black as the message's age increases. If a new message comes in from the same source, I wanted to replace the text of the old message with the new message, then have the text fade from red to black all over again.



      When I use a Stateful widget with a RestartableTimer, and I first start my UI, everything seems to work fine. However, as soon as the second message comes in from a particular source, that's where things break. If I use a plain Text() to display the new message, it works just fine. But if I use a Stateful widget to display the text and fade from red to black, the UI remains stale and no amount of updating seems to do the trick.



      My hierarchy (with layout-specific stuff removed) looks like:



      Stateful Container for different sources
      |
      List View
      |
      +--- Stateless Custom Widget
      |
      +-- Stateless Text (displays the source)
      |
      +-- Stateful Custom Text class
      <repeated for each source>


      If I replace my custom class with a plain Text(), then suddenly the text updates just fine (but there's no fading of color).



      Stateless Custom Widget



        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);


      Stateful Custom Widget



      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);
      }
      }









      share|improve this question














      Using stateful widgets causing stale widgets to be displayed



      I have a UI that receives update text updates over the network. When an update comes in, I wish to first show it in red, then have it slowly fade to black as the message's age increases. If a new message comes in from the same source, I wanted to replace the text of the old message with the new message, then have the text fade from red to black all over again.



      When I use a Stateful widget with a RestartableTimer, and I first start my UI, everything seems to work fine. However, as soon as the second message comes in from a particular source, that's where things break. If I use a plain Text() to display the new message, it works just fine. But if I use a Stateful widget to display the text and fade from red to black, the UI remains stale and no amount of updating seems to do the trick.



      My hierarchy (with layout-specific stuff removed) looks like:



      Stateful Container for different sources
      |
      List View
      |
      +--- Stateless Custom Widget
      |
      +-- Stateless Text (displays the source)
      |
      +-- Stateful Custom Text class
      <repeated for each source>


      If I replace my custom class with a plain Text(), then suddenly the text updates just fine (but there's no fading of color).



      Stateless Custom Widget



        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);


      Stateful Custom Widget



      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);
      }
      }






      animation flutter stateful






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Dec 28 '18 at 21:42









      jeffjeff

      111




      111
























          1 Answer
          1






          active

          oldest

          votes


















          0














          I think you have to change the design of the FlashText widget and use the didUpdateWidget method to rebuild when the widget text changes.



          I have implemented below a full app using a text field and a button to simulate the text coming from the server.



          I think it is more or less what you need but it might require some tweaks.



          import 'dart:async';

          import 'package:flutter/material.dart';

          void main() => runApp(MyApp());

          class MyApp extends StatelessWidget {
          @override
          Widget build(BuildContext context) {
          return MaterialApp(
          home: MyHomePage(),
          );
          }
          }

          class MyHomePage extends StatefulWidget {
          @override
          _MyHomePageState createState() => _MyHomePageState();
          }

          class _MyHomePageState extends State<MyHomePage> {
          var _cont = TextEditingController();

          String text = "qwertrrr";

          @override
          Widget build(BuildContext context) {
          return Scaffold(
          appBar: AppBar(
          title: Text("Test"),
          ),
          body: Column(
          children: <Widget>[
          TextFormField(
          controller: _cont,
          ),
          RaisedButton(
          child: new Text("Test"),
          onPressed: () => setState(() {
          text = _cont.text;
          }),
          ),
          FlashText(text, Colors.red, Colors.black, 10),
          ],
          ),
          );
          }
          }

          class FlashText extends StatefulWidget {
          final Color color0;
          final Color color1;
          final int duration;
          final String text;

          FlashText(this.text, this.color0, this.color1, this.duration);

          @override
          _FlashTextState createState() {
          return _FlashTextState();
          }
          }

          class _FlashTextState extends State<FlashText>
          with SingleTickerProviderStateMixin<FlashText> {
          Animation<Color> _animation;
          AnimationController _controller;

          Timer timer;

          @override
          void didUpdateWidget(FlashText oldWidget) {
          if (widget.text != oldWidget.text) {
          _controller.forward(from: 0.0);
          }
          super.didUpdateWidget(oldWidget);
          }

          @override
          Widget build(BuildContext ctx) {
          return Text(
          widget.text,
          style: TextStyle(color: _animation.value),
          );
          }

          @override
          void initState() {
          super.initState();
          _controller = AnimationController(
          vsync: this, duration: Duration(seconds: widget.duration));
          _animation = ColorTween(begin: widget.color0, end: widget.color1)
          .animate(_controller)
          ..addListener(() => setState(() {}));
          _controller.forward();
          }
          }





          share|improve this answer
























          • thanks, that pretty much works. a couple points:

            – jeff
            Dec 29 '18 at 7:32











          • Thanks! That led me on the right track. Here's what I've learned. 1) State subclasses shouldn't contain the actual state they wish to display. Use the corresponding widget to hold it. 2) Use the State classes widget property to access that information (I didn't realize it even existed, the tutorials are all so bare bones that they never mention it). When I removed my fields from State and added them to the Widget, the text was fixed. 3) When wanting to display something related to time, hold the timer-related mutable state in the state class (e.g. an animation object, timer callback).

            – jeff
            Dec 29 '18 at 7:40











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53964571%2fmix-of-stateful-and-stateless-flutter-ui-not-getting-updated%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          0














          I think you have to change the design of the FlashText widget and use the didUpdateWidget method to rebuild when the widget text changes.



          I have implemented below a full app using a text field and a button to simulate the text coming from the server.



          I think it is more or less what you need but it might require some tweaks.



          import 'dart:async';

          import 'package:flutter/material.dart';

          void main() => runApp(MyApp());

          class MyApp extends StatelessWidget {
          @override
          Widget build(BuildContext context) {
          return MaterialApp(
          home: MyHomePage(),
          );
          }
          }

          class MyHomePage extends StatefulWidget {
          @override
          _MyHomePageState createState() => _MyHomePageState();
          }

          class _MyHomePageState extends State<MyHomePage> {
          var _cont = TextEditingController();

          String text = "qwertrrr";

          @override
          Widget build(BuildContext context) {
          return Scaffold(
          appBar: AppBar(
          title: Text("Test"),
          ),
          body: Column(
          children: <Widget>[
          TextFormField(
          controller: _cont,
          ),
          RaisedButton(
          child: new Text("Test"),
          onPressed: () => setState(() {
          text = _cont.text;
          }),
          ),
          FlashText(text, Colors.red, Colors.black, 10),
          ],
          ),
          );
          }
          }

          class FlashText extends StatefulWidget {
          final Color color0;
          final Color color1;
          final int duration;
          final String text;

          FlashText(this.text, this.color0, this.color1, this.duration);

          @override
          _FlashTextState createState() {
          return _FlashTextState();
          }
          }

          class _FlashTextState extends State<FlashText>
          with SingleTickerProviderStateMixin<FlashText> {
          Animation<Color> _animation;
          AnimationController _controller;

          Timer timer;

          @override
          void didUpdateWidget(FlashText oldWidget) {
          if (widget.text != oldWidget.text) {
          _controller.forward(from: 0.0);
          }
          super.didUpdateWidget(oldWidget);
          }

          @override
          Widget build(BuildContext ctx) {
          return Text(
          widget.text,
          style: TextStyle(color: _animation.value),
          );
          }

          @override
          void initState() {
          super.initState();
          _controller = AnimationController(
          vsync: this, duration: Duration(seconds: widget.duration));
          _animation = ColorTween(begin: widget.color0, end: widget.color1)
          .animate(_controller)
          ..addListener(() => setState(() {}));
          _controller.forward();
          }
          }





          share|improve this answer
























          • thanks, that pretty much works. a couple points:

            – jeff
            Dec 29 '18 at 7:32











          • Thanks! That led me on the right track. Here's what I've learned. 1) State subclasses shouldn't contain the actual state they wish to display. Use the corresponding widget to hold it. 2) Use the State classes widget property to access that information (I didn't realize it even existed, the tutorials are all so bare bones that they never mention it). When I removed my fields from State and added them to the Widget, the text was fixed. 3) When wanting to display something related to time, hold the timer-related mutable state in the state class (e.g. an animation object, timer callback).

            – jeff
            Dec 29 '18 at 7:40
















          0














          I think you have to change the design of the FlashText widget and use the didUpdateWidget method to rebuild when the widget text changes.



          I have implemented below a full app using a text field and a button to simulate the text coming from the server.



          I think it is more or less what you need but it might require some tweaks.



          import 'dart:async';

          import 'package:flutter/material.dart';

          void main() => runApp(MyApp());

          class MyApp extends StatelessWidget {
          @override
          Widget build(BuildContext context) {
          return MaterialApp(
          home: MyHomePage(),
          );
          }
          }

          class MyHomePage extends StatefulWidget {
          @override
          _MyHomePageState createState() => _MyHomePageState();
          }

          class _MyHomePageState extends State<MyHomePage> {
          var _cont = TextEditingController();

          String text = "qwertrrr";

          @override
          Widget build(BuildContext context) {
          return Scaffold(
          appBar: AppBar(
          title: Text("Test"),
          ),
          body: Column(
          children: <Widget>[
          TextFormField(
          controller: _cont,
          ),
          RaisedButton(
          child: new Text("Test"),
          onPressed: () => setState(() {
          text = _cont.text;
          }),
          ),
          FlashText(text, Colors.red, Colors.black, 10),
          ],
          ),
          );
          }
          }

          class FlashText extends StatefulWidget {
          final Color color0;
          final Color color1;
          final int duration;
          final String text;

          FlashText(this.text, this.color0, this.color1, this.duration);

          @override
          _FlashTextState createState() {
          return _FlashTextState();
          }
          }

          class _FlashTextState extends State<FlashText>
          with SingleTickerProviderStateMixin<FlashText> {
          Animation<Color> _animation;
          AnimationController _controller;

          Timer timer;

          @override
          void didUpdateWidget(FlashText oldWidget) {
          if (widget.text != oldWidget.text) {
          _controller.forward(from: 0.0);
          }
          super.didUpdateWidget(oldWidget);
          }

          @override
          Widget build(BuildContext ctx) {
          return Text(
          widget.text,
          style: TextStyle(color: _animation.value),
          );
          }

          @override
          void initState() {
          super.initState();
          _controller = AnimationController(
          vsync: this, duration: Duration(seconds: widget.duration));
          _animation = ColorTween(begin: widget.color0, end: widget.color1)
          .animate(_controller)
          ..addListener(() => setState(() {}));
          _controller.forward();
          }
          }





          share|improve this answer
























          • thanks, that pretty much works. a couple points:

            – jeff
            Dec 29 '18 at 7:32











          • Thanks! That led me on the right track. Here's what I've learned. 1) State subclasses shouldn't contain the actual state they wish to display. Use the corresponding widget to hold it. 2) Use the State classes widget property to access that information (I didn't realize it even existed, the tutorials are all so bare bones that they never mention it). When I removed my fields from State and added them to the Widget, the text was fixed. 3) When wanting to display something related to time, hold the timer-related mutable state in the state class (e.g. an animation object, timer callback).

            – jeff
            Dec 29 '18 at 7:40














          0












          0








          0







          I think you have to change the design of the FlashText widget and use the didUpdateWidget method to rebuild when the widget text changes.



          I have implemented below a full app using a text field and a button to simulate the text coming from the server.



          I think it is more or less what you need but it might require some tweaks.



          import 'dart:async';

          import 'package:flutter/material.dart';

          void main() => runApp(MyApp());

          class MyApp extends StatelessWidget {
          @override
          Widget build(BuildContext context) {
          return MaterialApp(
          home: MyHomePage(),
          );
          }
          }

          class MyHomePage extends StatefulWidget {
          @override
          _MyHomePageState createState() => _MyHomePageState();
          }

          class _MyHomePageState extends State<MyHomePage> {
          var _cont = TextEditingController();

          String text = "qwertrrr";

          @override
          Widget build(BuildContext context) {
          return Scaffold(
          appBar: AppBar(
          title: Text("Test"),
          ),
          body: Column(
          children: <Widget>[
          TextFormField(
          controller: _cont,
          ),
          RaisedButton(
          child: new Text("Test"),
          onPressed: () => setState(() {
          text = _cont.text;
          }),
          ),
          FlashText(text, Colors.red, Colors.black, 10),
          ],
          ),
          );
          }
          }

          class FlashText extends StatefulWidget {
          final Color color0;
          final Color color1;
          final int duration;
          final String text;

          FlashText(this.text, this.color0, this.color1, this.duration);

          @override
          _FlashTextState createState() {
          return _FlashTextState();
          }
          }

          class _FlashTextState extends State<FlashText>
          with SingleTickerProviderStateMixin<FlashText> {
          Animation<Color> _animation;
          AnimationController _controller;

          Timer timer;

          @override
          void didUpdateWidget(FlashText oldWidget) {
          if (widget.text != oldWidget.text) {
          _controller.forward(from: 0.0);
          }
          super.didUpdateWidget(oldWidget);
          }

          @override
          Widget build(BuildContext ctx) {
          return Text(
          widget.text,
          style: TextStyle(color: _animation.value),
          );
          }

          @override
          void initState() {
          super.initState();
          _controller = AnimationController(
          vsync: this, duration: Duration(seconds: widget.duration));
          _animation = ColorTween(begin: widget.color0, end: widget.color1)
          .animate(_controller)
          ..addListener(() => setState(() {}));
          _controller.forward();
          }
          }





          share|improve this answer













          I think you have to change the design of the FlashText widget and use the didUpdateWidget method to rebuild when the widget text changes.



          I have implemented below a full app using a text field and a button to simulate the text coming from the server.



          I think it is more or less what you need but it might require some tweaks.



          import 'dart:async';

          import 'package:flutter/material.dart';

          void main() => runApp(MyApp());

          class MyApp extends StatelessWidget {
          @override
          Widget build(BuildContext context) {
          return MaterialApp(
          home: MyHomePage(),
          );
          }
          }

          class MyHomePage extends StatefulWidget {
          @override
          _MyHomePageState createState() => _MyHomePageState();
          }

          class _MyHomePageState extends State<MyHomePage> {
          var _cont = TextEditingController();

          String text = "qwertrrr";

          @override
          Widget build(BuildContext context) {
          return Scaffold(
          appBar: AppBar(
          title: Text("Test"),
          ),
          body: Column(
          children: <Widget>[
          TextFormField(
          controller: _cont,
          ),
          RaisedButton(
          child: new Text("Test"),
          onPressed: () => setState(() {
          text = _cont.text;
          }),
          ),
          FlashText(text, Colors.red, Colors.black, 10),
          ],
          ),
          );
          }
          }

          class FlashText extends StatefulWidget {
          final Color color0;
          final Color color1;
          final int duration;
          final String text;

          FlashText(this.text, this.color0, this.color1, this.duration);

          @override
          _FlashTextState createState() {
          return _FlashTextState();
          }
          }

          class _FlashTextState extends State<FlashText>
          with SingleTickerProviderStateMixin<FlashText> {
          Animation<Color> _animation;
          AnimationController _controller;

          Timer timer;

          @override
          void didUpdateWidget(FlashText oldWidget) {
          if (widget.text != oldWidget.text) {
          _controller.forward(from: 0.0);
          }
          super.didUpdateWidget(oldWidget);
          }

          @override
          Widget build(BuildContext ctx) {
          return Text(
          widget.text,
          style: TextStyle(color: _animation.value),
          );
          }

          @override
          void initState() {
          super.initState();
          _controller = AnimationController(
          vsync: this, duration: Duration(seconds: widget.duration));
          _animation = ColorTween(begin: widget.color0, end: widget.color1)
          .animate(_controller)
          ..addListener(() => setState(() {}));
          _controller.forward();
          }
          }






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Dec 29 '18 at 0:08









          chemamolinschemamolins

          2,4841817




          2,4841817













          • thanks, that pretty much works. a couple points:

            – jeff
            Dec 29 '18 at 7:32











          • Thanks! That led me on the right track. Here's what I've learned. 1) State subclasses shouldn't contain the actual state they wish to display. Use the corresponding widget to hold it. 2) Use the State classes widget property to access that information (I didn't realize it even existed, the tutorials are all so bare bones that they never mention it). When I removed my fields from State and added them to the Widget, the text was fixed. 3) When wanting to display something related to time, hold the timer-related mutable state in the state class (e.g. an animation object, timer callback).

            – jeff
            Dec 29 '18 at 7:40



















          • thanks, that pretty much works. a couple points:

            – jeff
            Dec 29 '18 at 7:32











          • Thanks! That led me on the right track. Here's what I've learned. 1) State subclasses shouldn't contain the actual state they wish to display. Use the corresponding widget to hold it. 2) Use the State classes widget property to access that information (I didn't realize it even existed, the tutorials are all so bare bones that they never mention it). When I removed my fields from State and added them to the Widget, the text was fixed. 3) When wanting to display something related to time, hold the timer-related mutable state in the state class (e.g. an animation object, timer callback).

            – jeff
            Dec 29 '18 at 7:40

















          thanks, that pretty much works. a couple points:

          – jeff
          Dec 29 '18 at 7:32





          thanks, that pretty much works. a couple points:

          – jeff
          Dec 29 '18 at 7:32













          Thanks! That led me on the right track. Here's what I've learned. 1) State subclasses shouldn't contain the actual state they wish to display. Use the corresponding widget to hold it. 2) Use the State classes widget property to access that information (I didn't realize it even existed, the tutorials are all so bare bones that they never mention it). When I removed my fields from State and added them to the Widget, the text was fixed. 3) When wanting to display something related to time, hold the timer-related mutable state in the state class (e.g. an animation object, timer callback).

          – jeff
          Dec 29 '18 at 7:40





          Thanks! That led me on the right track. Here's what I've learned. 1) State subclasses shouldn't contain the actual state they wish to display. Use the corresponding widget to hold it. 2) Use the State classes widget property to access that information (I didn't realize it even existed, the tutorials are all so bare bones that they never mention it). When I removed my fields from State and added them to the Widget, the text was fixed. 3) When wanting to display something related to time, hold the timer-related mutable state in the state class (e.g. an animation object, timer callback).

          – jeff
          Dec 29 '18 at 7:40


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53964571%2fmix-of-stateful-and-stateless-flutter-ui-not-getting-updated%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Ue1pMRj3WhMVGddA,MZcSO kOsB,wJR
          xWmREygveK7ndcqMGqt A6,6X hTnfIRq6,CAy uyEL2o3qrDOUVPlVF,VL wo4U92OC,33aiMQuvSTuJkatOw

          Popular posts from this blog

          Monofisismo

          Angular Downloading a file using contenturl with Basic Authentication

          Olmecas