title: setState() or markNeedsBuild() called during build on ListView
body: <p>So I am trying to refactor my listView logic. Basically my ListView has become cumbersome with the UI logic , so I decided, why not move certain parts of the UI logic to another class</p>
  
  <p>This is my code
  ListPage.dart </p>
  
  <pre><code>import 'package:flutter/material.dart';
  import 'package:flutter/services.dart';
  import 'package:flutter/widgets.dart';
  import 'package:sample_flutter_works/ListTextArea.dart';
  import 'package:sample_flutter_works/Model.dart';
  import 'dart:convert';
  import 'package:sample_flutter_works/RefreshTableContainer.dart';
  
  class ListPage extends StatefulWidget {
    @override
    MyListPage createState() =&gt; MyListPage();
  }
  
  class MyListPage extends State&lt;ListPage&gt; {
    MessageList messageList;
    List&lt;int&gt; viewTimeInfo;
    ScrollController _controller;
  
    _scrollListener() {
  
    }
  
    @override
    void initState() {
       super.initState();
      SystemChrome.setPreferredOrientations(
          [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
  
      _controller = ScrollController();
      _controller.addListener(_scrollListener);
  
      loadMessages(
          completionBlock: (dataSet) =&gt; {
                setState(() {
                  messageList = dataSet;
                })
              });
    }
  
    void loadMessages({completionBlock}) async {
      var jsonString = await rootBundle.loadString('assets/Chat.json');
      final jsonResponse = json.decode(jsonString);
      if (jsonResponse != null) {
        completionBlock(MessageList.fromJSON(jsonResponse));
      } else {
        completionBlock(null);
      }
    }
  
    Widget listLayout() {
      return ListView.separated(
          padding: const EdgeInsets.all(8.0),
          itemCount: (messageList != null &amp;&amp; messageList.msgList != null)
              ? messageList.msgList.length
              : 0,
          separatorBuilder: (context, index) =&gt; Divider(
                color: Colors.black,
                height: 4.0,
              ),
          itemBuilder: (BuildContext context, int index) {
            var msgValToSend =
                (messageList != null &amp;&amp; messageList.msgList != null)
                    ? messageList.msgList[index]
                    : null;
  
            return Stack(
              children: &lt;Widget&gt;[
                IntrinsicHeight(
                  child: Row(
                    children: &lt;Widget&gt;[
                      getTheImageLayout(msgValToSend),
                      new ListTextArea(
                          msg: msgValToSend,
                          didTapOnTextArea: tappedOnTextArea,
                          visibilityCheck: checkForVisibility)
                    ],
                  ),
                )
              ],
            );
          });
    }
  
  
    tappedOnTextArea(Message msg) {
      var viewedInfo = this.viewTimeInfo;
      if (viewedInfo != null) {
        var indexOfTappedElement = viewedInfo.indexOf(msg.messageID);
  
        if (indexOfTappedElement != null &amp;&amp; indexOfTappedElement != -1) {
          viewedInfo.removeAt(indexOfTappedElement);
        } else {
          viewedInfo.add(msg.messageID);
        }
      } else {
        viewedInfo = [msg.messageID];
      }
  
      setState(() {
                viewTimeInfo = viewedInfo;
              });
    }
  
    checkForVisibility(bool _visible, Message msg) {
      if (msg != null &amp;&amp; this.viewTimeInfo != null) {
        var checkForIndex = this.viewTimeInfo.indexOf(msg.messageID);
        if (checkForIndex != null &amp;&amp; checkForIndex != -1) {
          _visible = true;
        }
      }
    }
  
  
    Widget getTheImageLayout(Message msg) {
      return Expanded(
          flex: 2,
          child: Align(
              alignment: Alignment.topLeft,
              child: Padding(
                padding: EdgeInsets.fromLTRB(5, 2.5, 0, 0),
                child: Container(
                    color: Colors.red,
                    height: 50,
                    child: Row(
                      children: &lt;Widget&gt;[
                        userImageView(msg),
                      ],
                    )),
              )));
    }
  
    Widget userImageView(Message msg) {
      return Expanded(
          flex: 8,
          child: Align(
              alignment: Alignment.centerLeft,
              child: Container(
                  width: 40.0,
                  height: 40.0,
                  decoration:
                      BoxDecoration(shape: BoxShape.circle, color: Colors.green),
                  child: ClipOval(
                    child: Image.network(
                      (msg.msgUser.userPicUrl != null)
                          ? msg.msgUser.userPicUrl
                          : 'https://picsum.photos/250?image=9',
                      fit: BoxFit.fill,
                    ),
                  ))));
    }
  
    Future&lt;void&gt; refreshTheChatTable() async {
      print(" This is where the logic of pulll 2 refresh must be written ");
  
      loadMessages(
          completionBlock: (dataSet) =&gt; {
                setState(() {
                  messageList = dataSet;
                })
              });
    }
  
    @override
    Widget build(BuildContext context) {
      return new RefreshTableContainer(
        listLayout: listLayout(),
        pull2RefreshAction: refreshTheChatTable,
      );
    }
  }
  </code></pre>
  
  <p>ListTextArea.dart</p>
  
  <pre><code>import 'package:flutter/material.dart';
  import 'package:flutter/widgets.dart';
  import 'package:sample_flutter_works/Model.dart';
  
  class ListTextArea extends StatelessWidget {
  
    Message msg;
    Function didTapOnTextArea;
    Function visibilityCheck;
  
    ListTextArea({
      this.msg,
      this.didTapOnTextArea,
      this.visibilityCheck
    });
  
    @override
    Widget build(BuildContext context) {
      return Expanded(
          flex: 8,
          child: GestureDetector(
            onTap: didTapOnTextArea(msg),
            child: Padding(
              padding: EdgeInsets.fromLTRB(0, 2.5, 10, 0),
              child: Column(
                children: getChildWidgetArray(msg) ,
              ),
            ),
          ));
    }
  
    List&lt;Widget&gt; getChildWidgetArray(Message msg) {
  
      var elementalArray = [
        Align(
          alignment: Alignment.topLeft,
          child: Text(
            (msg != null) ? msg.msgContent.content : "Data Loading",
            style: TextStyle(
              background: Paint()..color = Colors.orange,
            ),
          ),
        ),
        Spacer(), // Defaults to a flex of one.
        Align(
          alignment: Alignment.bottomRight,
          child: Text(
            'Date of sending',
            textDirection: TextDirection.rtl,
            style: TextStyle(
              background: Paint()..color = Colors.blue,
            ),
          ),
        )
      ];
  
      var _visible = false;
      visibilityCheck(_visible,msg);
  
      var timeInfo = AnimatedOpacity (
            opacity: _visible ? 1.0 : 0.0,
            duration: Duration(milliseconds: 500),
            child: Align(
              child: _visible ? (Align(alignment: Alignment.topLeft,child:Column(children: &lt;Widget&gt;[Text("Last Read :" + (msg.msgTimeInfo.lastReadInfo)),
                                        Text("Delievered :" + (msg.msgTimeInfo.deliveredInfo))],))): null));
          elementalArray.add(timeInfo);
  
      return elementalArray;
    }
  }
  </code></pre>
  
  <p>The error is as follows:
  <a href="https://i.stack.imgur.com/xVJjt.png" rel="noreferrer"><img src="https://i.stack.imgur.com/xVJjt.png" alt="enter image description here"></a></p>
  
  <p>What I am trying to do ( or had done earlier on when the entire code was in ListPage.dart ) was dynamically calculated cells in a listView, each cell responding to a tap action that shows in more data. I don't understand what I did wrong here at all.</p>
  
  <p>I called the setState in init but inside a callback function. The statelesswidget ListTextArea will not handle the state at all, but returns the tapAction to the StateFulWidget ListPage.dart.</p>
  
  <p>So why am I getting this error. Any insights would be helpful. </p>