title: Flutter - How to update state (or value?) of a Future/List used to build ListView (via FutureBuilder)
body: <p>Im pasting relevant code below, but you may be able to answer it based upon my pseudo-explanation.</p>
  
  <p>Im using a FutureBuilder to build a listview.  </p>
  
  <ul>
  <li>I start off by using init() to async HTTP call the API and parse that into an List of objects (Location) mapped to represent the json result.  </li>
  <li>That list of Location(s) is then returned into the <code>Future&lt;List&lt;Location&gt;&gt; _listFuture</code> variable (which is the future for the FutureBuilder).  </li>
  <li>Once the future "returns" or "finishes" the FutureBuilder kicks off and uses ListView.builder/Container/ListTile to loop through and build the list.  </li>
  <li>At some point, Im going to want an onTap() handler (in the ListTile) that changes the background color of whatever list item is selected.  </li>
  <li>To support that, I have a backgroundColor member in the Location class (that holds the JSON responses) that I default to "#fc7303" for all items (assume everything is always initially unchecked).  i then want to change the background of whatever is selected to "#34bdeb" in onTap().  </li>
  <li>I'm assuming that I could call setState() which would trigger a refresh and the new background color would be noticed/used on redraw.</li>
  </ul>
  
  <p>The problem is that the ListView/Contrainer/ListTile is driven by a </p>
  
  <pre><code>Future&lt;List&lt;Location&gt;&gt;
  </code></pre>
  
  <p>.  I can pass the "tapped" index to my ontap handler, but I dont believe I can have my _changeBackground() just update the backgroundColor value for the selected index and call setState() because you cannot directly access/update a future like that (I get the error <code>ERROR: The operator '[]' isn't defined for the class 'Future&lt;List&lt;Location&gt;&gt;'.</code>)</p>
  
  <p>Im not sure Im taking the right approach.  In this case, I guess I could always theoretically separate the "background" color tracking into a new separate List (outside of the future) and track/reference it that way using aligned indexes from onTap().  </p>
  
  <p>However, I am not sure that would always work.  In the future, I might need to actually change the values/state of what was returned in the future.  For instance, think of if I wanted to be able to click on a list item and update the "companyName".  In this case, I would be changing a value stored in the future directly.  I guess I could technically send the new name to the server and completely refresh the list that way, but that seems inefficient (what if they decide to "cancel" and not save changes?).</p>
  
  <p>Any help is appreciated.  thanks!</p>
  
  <p>this class actually holds the relevant data for the list</p>
  
  <pre><code>// Location
  class Location {
  
    // members
    String locationID;
    String locationName;
    String companyName;
    String backgroundColor = 'fc7303';
  
    // constructor?
    Location({this.locationID, this.locationName, this.companyName});
  
    // factory?
    factory Location.fromJson(Map&lt;String, dynamic&gt; json) {
      return Location(
        locationID: json['locationID'],
        locationName: json['locationName'],
        companyName: json['companyName'],
      );
  
    }
  
  }
  </code></pre>
  
  <p>this class is the parent json response that has "result" (success/error) messages.  it instantiates the class above as a list to track the actual company/location records </p>
  
  <pre><code>//jsonResponse
  class jsonResponse{
  
    String result;
    String resultMsg;
    List&lt;Location&gt; locations;
  
    jsonResponse({this.result, this.resultMsg, this.locations});
  
    factory jsonResponse.fromJson(Map&lt;String, dynamic&gt; parsedJson){
  
      var list = parsedJson['resultSet'] as List;
      List&lt;Location&gt; locationList = list.map((i) =&gt; Location.fromJson(i)).toList();
      return jsonResponse(
          result: parsedJson['result'],
          resultMsg: parsedJson['resultMsg'],
          locations: locationList
      );
    }
  
  } // jsonResponse
  </code></pre>
  
  <p>here is the state and stateful widgets that use the classes above to parse API data and create ListView</p>
  
  <pre><code>class locationsApiState extends State&lt;locationsApiWidget&gt; {
  
    // list to track AJAX results
    Future&lt;List&lt;Location&gt;&gt; _listFuture;
  
    // init - set initial values
    @override
    void initState() {
      super.initState();
      // initial load
      _listFuture = updateAndGetList();
    }
  
    Future&lt;List&lt;Location&gt;&gt; updateAndGetList() async {
  
      var response = await http.get("http://XXX.XXX.XXX.XXX/api/listCompanies.php");
      if (response.statusCode == 200) {
        var r1 = json.decode(response.body);
        jsonResponse r = new jsonResponse.fromJson(r1);
        return r.locations;
      } else {
        throw Exception('Failed to load internet');
      }
  
    }
  
    _changeBackground(int index){
      print("in changebackground(): ${index}");       // this works!
      _listFuture[index].backgroundColor = '34bdeb';   // ERROR: The operator '[]' isn't defined for the class 'Future&lt;List&lt;Location&gt;&gt;'.
    }
  
    // build() method
    @override
    Widget build(BuildContext context) {
  
      return new FutureBuilder&lt;List&lt;Location&gt;&gt;(
          future: _listFuture,
          builder: (context, snapshot){
  
            if (snapshot.connectionState == ConnectionState.waiting) {
              return new Center(
                child: new CircularProgressIndicator(),
              );
            } else if (snapshot.hasError) {
              return new Text('Error: ${snapshot.error}');
            } else {
              final items = snapshot.data;
              return new Scrollbar(
                child: new RefreshIndicator(
                    child: ListView.builder(
                      physics: const AlwaysScrollableScrollPhysics(),
                      //Even if zero elements to update scroll
                      itemCount: items.length,
                      itemBuilder: (context, index) {
                        return
                          Container(
                              color: HexColor(items[index].backgroundColor),
                              child:
                              ListTile(
                                title: Text(items[index].companyName),
                                onTap: () {
                                  print("Item at $index is ${items[index].companyName}");
                                  _changeBackground(index);
                                }  // onTap
                              )
                          );
                      },
                    ),
                    onRefresh: () {
                      // implement later
                      return;
                    } // refreshList,
                ),
              );
            }// else
          } // builder
      ); // FutureBuilder
    } // build
  } // locationsApiState class
  
  
  class locationsApiWidget extends StatefulWidget {
    @override
    locationsApiState createState() =&gt; locationsApiState();
  }
  </code></pre>
  
  <p>helper class (taken from somewhere on stackoverflow) for converting HEX to integer colors</p>
  
  <pre><code>class HexColor extends Color {
    static int _getColorFromHex(String hexColor) {
      hexColor = hexColor.toUpperCase().replaceAll("#", "");
      if (hexColor.length == 6) {
        hexColor = "FF" + hexColor;
      }
      return int.parse(hexColor, radix: 16);
    }
  
    HexColor(final String hexColor) : super(_getColorFromHex(hexColor));
  }
  </code></pre>
  
  <p>Thanks!</p>