How do you convert a list future to a list to use as a variable not a widget?












1















I'm trying to implement the PaginatedDataTable class in flutter. A required field in the constructor of this class, is the class DataTableSource. Looking at the data table example in the material section of the flutter gallery examples here. There is a member variable for the DataTableSource called List<Dessert> _desserts where it's values are hard coded. In my implementation, I'm making a http call and returning some json to be decoded.



List<Result> parseResults(String responseBody) {
final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();

return parsed.map<Result>((json) => Result.fromJson(json)).toList();
}

Future<List<Result>> fetchResults(http.Client client) async {
final response = await client.get('https://api.myjson.com/bins/j5xau');

// Use the compute function to run parseResults in a separate isolate
return compute(parseResults, response.body);


In my DataTableSource class I'm not sure how to instantiate the list.



`final List<Result> results = fetchResults(http.Client);` 


doesn't compile because fetchResults() returns a future. If I change the return type to a future the results does compile but I need my returned json to be of type List so I can use methods like sort etc..How should I convert the future to a list.










share|improve this question



























    1















    I'm trying to implement the PaginatedDataTable class in flutter. A required field in the constructor of this class, is the class DataTableSource. Looking at the data table example in the material section of the flutter gallery examples here. There is a member variable for the DataTableSource called List<Dessert> _desserts where it's values are hard coded. In my implementation, I'm making a http call and returning some json to be decoded.



    List<Result> parseResults(String responseBody) {
    final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();

    return parsed.map<Result>((json) => Result.fromJson(json)).toList();
    }

    Future<List<Result>> fetchResults(http.Client client) async {
    final response = await client.get('https://api.myjson.com/bins/j5xau');

    // Use the compute function to run parseResults in a separate isolate
    return compute(parseResults, response.body);


    In my DataTableSource class I'm not sure how to instantiate the list.



    `final List<Result> results = fetchResults(http.Client);` 


    doesn't compile because fetchResults() returns a future. If I change the return type to a future the results does compile but I need my returned json to be of type List so I can use methods like sort etc..How should I convert the future to a list.










    share|improve this question

























      1












      1








      1








      I'm trying to implement the PaginatedDataTable class in flutter. A required field in the constructor of this class, is the class DataTableSource. Looking at the data table example in the material section of the flutter gallery examples here. There is a member variable for the DataTableSource called List<Dessert> _desserts where it's values are hard coded. In my implementation, I'm making a http call and returning some json to be decoded.



      List<Result> parseResults(String responseBody) {
      final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();

      return parsed.map<Result>((json) => Result.fromJson(json)).toList();
      }

      Future<List<Result>> fetchResults(http.Client client) async {
      final response = await client.get('https://api.myjson.com/bins/j5xau');

      // Use the compute function to run parseResults in a separate isolate
      return compute(parseResults, response.body);


      In my DataTableSource class I'm not sure how to instantiate the list.



      `final List<Result> results = fetchResults(http.Client);` 


      doesn't compile because fetchResults() returns a future. If I change the return type to a future the results does compile but I need my returned json to be of type List so I can use methods like sort etc..How should I convert the future to a list.










      share|improve this question














      I'm trying to implement the PaginatedDataTable class in flutter. A required field in the constructor of this class, is the class DataTableSource. Looking at the data table example in the material section of the flutter gallery examples here. There is a member variable for the DataTableSource called List<Dessert> _desserts where it's values are hard coded. In my implementation, I'm making a http call and returning some json to be decoded.



      List<Result> parseResults(String responseBody) {
      final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();

      return parsed.map<Result>((json) => Result.fromJson(json)).toList();
      }

      Future<List<Result>> fetchResults(http.Client client) async {
      final response = await client.get('https://api.myjson.com/bins/j5xau');

      // Use the compute function to run parseResults in a separate isolate
      return compute(parseResults, response.body);


      In my DataTableSource class I'm not sure how to instantiate the list.



      `final List<Result> results = fetchResults(http.Client);` 


      doesn't compile because fetchResults() returns a future. If I change the return type to a future the results does compile but I need my returned json to be of type List so I can use methods like sort etc..How should I convert the future to a list.







      dart flutter future






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 13 '18 at 19:50









      flutterflutter

      4423821




      4423821
























          1 Answer
          1






          active

          oldest

          votes


















          2














          In your DataTableSource class just remove the results variable. Then in your build function, you can use a FutureBuilder widget like this:



          FutureBuilder<List<Result>>(
          future: fetchResults(http.Client),
          builder: (BuildContext context, AsyncSnapshot<List<Result>> snapshot) {
          switch (snapshot.connectionState) {
          case ConnectionState.none:
          return Text('Press button to start.');
          case ConnectionState.active:
          case ConnectionState.waiting:
          return Text('Awaiting result...');
          case ConnectionState.done:
          if (snapshot.hasError)
          return Text('Error: ${snapshot.error}');
          return Text('Result: ${snapshot.data}');
          }
          return null; // unreachable
          },
          )


          Note that snapshot.data is a List<Result> now and you can use it in the same way you were using it back when it was a hard coded value.



          Edit:



          If you don't want to use a FutureBuilder I would suggest that you have a function that basically modifies the value of the results when the http call completes. Here's an example of what I mean:



          Make DessertDataSource take in a List<Result> in its constructor to define the value of results like so:



          class DessertDataSource extends DataTableSource {
          final List<Result> results;
          DessertDataSource(this.results);
          // rest of the class
          }


          In the _DataTableDemoState, make _dessertsDataSource no longer final and change its initial value to DessertDataSource(). Also, add a boolean indicating when the data is loaded already or not.



          class _DataTableDemoState extends State<DataTableDemo> {
          // other fields!
          DessertDataSource _dessertsDataSource = DessertDataSource();
          bool isLoaded = false;


          Then add the following function to _DataTableDemoState. The boolean ensures we only make the http call once.



          Future<void> getData() async {
          final results = await fetchResults(http.Client);
          if (!isLoaded) {
          setState(() {
          _dessertsDataSource = DessertDataSource(results);
          isLoaded = true;
          });
          }
          }


          Finally call that function upon pressing a button or some other trigger or maybe just at the beginning of your build function.



          @override
          Widget build(BuildContext context) {
          getData();
          return MYWidget();
          }


          Then whenever the data is returned from the http call, the widget will automatically update with the new data.






          share|improve this answer


























          • Is there anyway to change the future to a list without using FutureBuilder. My class extends DataTableSource and I'd like to instantiate the list in that class because of the necessary sorting on the list by the implemented methods.

            – flutter
            Nov 13 '18 at 20:35













          • @user2387962 i edited it it describes a method where you don't need to use a FutureBuilder.

            – Ringil
            Nov 13 '18 at 21:17











          • thanks but (await fetchResults(http.Client)); doesn't compile

            – flutter
            Nov 14 '18 at 11:24













          • @user2387962 ah that was probably because it was inside setState... I edited it again

            – Ringil
            Nov 14 '18 at 12:50











          • cheers works perfect

            – flutter
            Nov 14 '18 at 16:23











          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%2f53288493%2fhow-do-you-convert-a-list-future-to-a-list-to-use-as-a-variable-not-a-widget%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









          2














          In your DataTableSource class just remove the results variable. Then in your build function, you can use a FutureBuilder widget like this:



          FutureBuilder<List<Result>>(
          future: fetchResults(http.Client),
          builder: (BuildContext context, AsyncSnapshot<List<Result>> snapshot) {
          switch (snapshot.connectionState) {
          case ConnectionState.none:
          return Text('Press button to start.');
          case ConnectionState.active:
          case ConnectionState.waiting:
          return Text('Awaiting result...');
          case ConnectionState.done:
          if (snapshot.hasError)
          return Text('Error: ${snapshot.error}');
          return Text('Result: ${snapshot.data}');
          }
          return null; // unreachable
          },
          )


          Note that snapshot.data is a List<Result> now and you can use it in the same way you were using it back when it was a hard coded value.



          Edit:



          If you don't want to use a FutureBuilder I would suggest that you have a function that basically modifies the value of the results when the http call completes. Here's an example of what I mean:



          Make DessertDataSource take in a List<Result> in its constructor to define the value of results like so:



          class DessertDataSource extends DataTableSource {
          final List<Result> results;
          DessertDataSource(this.results);
          // rest of the class
          }


          In the _DataTableDemoState, make _dessertsDataSource no longer final and change its initial value to DessertDataSource(). Also, add a boolean indicating when the data is loaded already or not.



          class _DataTableDemoState extends State<DataTableDemo> {
          // other fields!
          DessertDataSource _dessertsDataSource = DessertDataSource();
          bool isLoaded = false;


          Then add the following function to _DataTableDemoState. The boolean ensures we only make the http call once.



          Future<void> getData() async {
          final results = await fetchResults(http.Client);
          if (!isLoaded) {
          setState(() {
          _dessertsDataSource = DessertDataSource(results);
          isLoaded = true;
          });
          }
          }


          Finally call that function upon pressing a button or some other trigger or maybe just at the beginning of your build function.



          @override
          Widget build(BuildContext context) {
          getData();
          return MYWidget();
          }


          Then whenever the data is returned from the http call, the widget will automatically update with the new data.






          share|improve this answer


























          • Is there anyway to change the future to a list without using FutureBuilder. My class extends DataTableSource and I'd like to instantiate the list in that class because of the necessary sorting on the list by the implemented methods.

            – flutter
            Nov 13 '18 at 20:35













          • @user2387962 i edited it it describes a method where you don't need to use a FutureBuilder.

            – Ringil
            Nov 13 '18 at 21:17











          • thanks but (await fetchResults(http.Client)); doesn't compile

            – flutter
            Nov 14 '18 at 11:24













          • @user2387962 ah that was probably because it was inside setState... I edited it again

            – Ringil
            Nov 14 '18 at 12:50











          • cheers works perfect

            – flutter
            Nov 14 '18 at 16:23
















          2














          In your DataTableSource class just remove the results variable. Then in your build function, you can use a FutureBuilder widget like this:



          FutureBuilder<List<Result>>(
          future: fetchResults(http.Client),
          builder: (BuildContext context, AsyncSnapshot<List<Result>> snapshot) {
          switch (snapshot.connectionState) {
          case ConnectionState.none:
          return Text('Press button to start.');
          case ConnectionState.active:
          case ConnectionState.waiting:
          return Text('Awaiting result...');
          case ConnectionState.done:
          if (snapshot.hasError)
          return Text('Error: ${snapshot.error}');
          return Text('Result: ${snapshot.data}');
          }
          return null; // unreachable
          },
          )


          Note that snapshot.data is a List<Result> now and you can use it in the same way you were using it back when it was a hard coded value.



          Edit:



          If you don't want to use a FutureBuilder I would suggest that you have a function that basically modifies the value of the results when the http call completes. Here's an example of what I mean:



          Make DessertDataSource take in a List<Result> in its constructor to define the value of results like so:



          class DessertDataSource extends DataTableSource {
          final List<Result> results;
          DessertDataSource(this.results);
          // rest of the class
          }


          In the _DataTableDemoState, make _dessertsDataSource no longer final and change its initial value to DessertDataSource(). Also, add a boolean indicating when the data is loaded already or not.



          class _DataTableDemoState extends State<DataTableDemo> {
          // other fields!
          DessertDataSource _dessertsDataSource = DessertDataSource();
          bool isLoaded = false;


          Then add the following function to _DataTableDemoState. The boolean ensures we only make the http call once.



          Future<void> getData() async {
          final results = await fetchResults(http.Client);
          if (!isLoaded) {
          setState(() {
          _dessertsDataSource = DessertDataSource(results);
          isLoaded = true;
          });
          }
          }


          Finally call that function upon pressing a button or some other trigger or maybe just at the beginning of your build function.



          @override
          Widget build(BuildContext context) {
          getData();
          return MYWidget();
          }


          Then whenever the data is returned from the http call, the widget will automatically update with the new data.






          share|improve this answer


























          • Is there anyway to change the future to a list without using FutureBuilder. My class extends DataTableSource and I'd like to instantiate the list in that class because of the necessary sorting on the list by the implemented methods.

            – flutter
            Nov 13 '18 at 20:35













          • @user2387962 i edited it it describes a method where you don't need to use a FutureBuilder.

            – Ringil
            Nov 13 '18 at 21:17











          • thanks but (await fetchResults(http.Client)); doesn't compile

            – flutter
            Nov 14 '18 at 11:24













          • @user2387962 ah that was probably because it was inside setState... I edited it again

            – Ringil
            Nov 14 '18 at 12:50











          • cheers works perfect

            – flutter
            Nov 14 '18 at 16:23














          2












          2








          2







          In your DataTableSource class just remove the results variable. Then in your build function, you can use a FutureBuilder widget like this:



          FutureBuilder<List<Result>>(
          future: fetchResults(http.Client),
          builder: (BuildContext context, AsyncSnapshot<List<Result>> snapshot) {
          switch (snapshot.connectionState) {
          case ConnectionState.none:
          return Text('Press button to start.');
          case ConnectionState.active:
          case ConnectionState.waiting:
          return Text('Awaiting result...');
          case ConnectionState.done:
          if (snapshot.hasError)
          return Text('Error: ${snapshot.error}');
          return Text('Result: ${snapshot.data}');
          }
          return null; // unreachable
          },
          )


          Note that snapshot.data is a List<Result> now and you can use it in the same way you were using it back when it was a hard coded value.



          Edit:



          If you don't want to use a FutureBuilder I would suggest that you have a function that basically modifies the value of the results when the http call completes. Here's an example of what I mean:



          Make DessertDataSource take in a List<Result> in its constructor to define the value of results like so:



          class DessertDataSource extends DataTableSource {
          final List<Result> results;
          DessertDataSource(this.results);
          // rest of the class
          }


          In the _DataTableDemoState, make _dessertsDataSource no longer final and change its initial value to DessertDataSource(). Also, add a boolean indicating when the data is loaded already or not.



          class _DataTableDemoState extends State<DataTableDemo> {
          // other fields!
          DessertDataSource _dessertsDataSource = DessertDataSource();
          bool isLoaded = false;


          Then add the following function to _DataTableDemoState. The boolean ensures we only make the http call once.



          Future<void> getData() async {
          final results = await fetchResults(http.Client);
          if (!isLoaded) {
          setState(() {
          _dessertsDataSource = DessertDataSource(results);
          isLoaded = true;
          });
          }
          }


          Finally call that function upon pressing a button or some other trigger or maybe just at the beginning of your build function.



          @override
          Widget build(BuildContext context) {
          getData();
          return MYWidget();
          }


          Then whenever the data is returned from the http call, the widget will automatically update with the new data.






          share|improve this answer















          In your DataTableSource class just remove the results variable. Then in your build function, you can use a FutureBuilder widget like this:



          FutureBuilder<List<Result>>(
          future: fetchResults(http.Client),
          builder: (BuildContext context, AsyncSnapshot<List<Result>> snapshot) {
          switch (snapshot.connectionState) {
          case ConnectionState.none:
          return Text('Press button to start.');
          case ConnectionState.active:
          case ConnectionState.waiting:
          return Text('Awaiting result...');
          case ConnectionState.done:
          if (snapshot.hasError)
          return Text('Error: ${snapshot.error}');
          return Text('Result: ${snapshot.data}');
          }
          return null; // unreachable
          },
          )


          Note that snapshot.data is a List<Result> now and you can use it in the same way you were using it back when it was a hard coded value.



          Edit:



          If you don't want to use a FutureBuilder I would suggest that you have a function that basically modifies the value of the results when the http call completes. Here's an example of what I mean:



          Make DessertDataSource take in a List<Result> in its constructor to define the value of results like so:



          class DessertDataSource extends DataTableSource {
          final List<Result> results;
          DessertDataSource(this.results);
          // rest of the class
          }


          In the _DataTableDemoState, make _dessertsDataSource no longer final and change its initial value to DessertDataSource(). Also, add a boolean indicating when the data is loaded already or not.



          class _DataTableDemoState extends State<DataTableDemo> {
          // other fields!
          DessertDataSource _dessertsDataSource = DessertDataSource();
          bool isLoaded = false;


          Then add the following function to _DataTableDemoState. The boolean ensures we only make the http call once.



          Future<void> getData() async {
          final results = await fetchResults(http.Client);
          if (!isLoaded) {
          setState(() {
          _dessertsDataSource = DessertDataSource(results);
          isLoaded = true;
          });
          }
          }


          Finally call that function upon pressing a button or some other trigger or maybe just at the beginning of your build function.



          @override
          Widget build(BuildContext context) {
          getData();
          return MYWidget();
          }


          Then whenever the data is returned from the http call, the widget will automatically update with the new data.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 14 '18 at 12:49

























          answered Nov 13 '18 at 19:59









          RingilRingil

          3,71521226




          3,71521226













          • Is there anyway to change the future to a list without using FutureBuilder. My class extends DataTableSource and I'd like to instantiate the list in that class because of the necessary sorting on the list by the implemented methods.

            – flutter
            Nov 13 '18 at 20:35













          • @user2387962 i edited it it describes a method where you don't need to use a FutureBuilder.

            – Ringil
            Nov 13 '18 at 21:17











          • thanks but (await fetchResults(http.Client)); doesn't compile

            – flutter
            Nov 14 '18 at 11:24













          • @user2387962 ah that was probably because it was inside setState... I edited it again

            – Ringil
            Nov 14 '18 at 12:50











          • cheers works perfect

            – flutter
            Nov 14 '18 at 16:23



















          • Is there anyway to change the future to a list without using FutureBuilder. My class extends DataTableSource and I'd like to instantiate the list in that class because of the necessary sorting on the list by the implemented methods.

            – flutter
            Nov 13 '18 at 20:35













          • @user2387962 i edited it it describes a method where you don't need to use a FutureBuilder.

            – Ringil
            Nov 13 '18 at 21:17











          • thanks but (await fetchResults(http.Client)); doesn't compile

            – flutter
            Nov 14 '18 at 11:24













          • @user2387962 ah that was probably because it was inside setState... I edited it again

            – Ringil
            Nov 14 '18 at 12:50











          • cheers works perfect

            – flutter
            Nov 14 '18 at 16:23

















          Is there anyway to change the future to a list without using FutureBuilder. My class extends DataTableSource and I'd like to instantiate the list in that class because of the necessary sorting on the list by the implemented methods.

          – flutter
          Nov 13 '18 at 20:35







          Is there anyway to change the future to a list without using FutureBuilder. My class extends DataTableSource and I'd like to instantiate the list in that class because of the necessary sorting on the list by the implemented methods.

          – flutter
          Nov 13 '18 at 20:35















          @user2387962 i edited it it describes a method where you don't need to use a FutureBuilder.

          – Ringil
          Nov 13 '18 at 21:17





          @user2387962 i edited it it describes a method where you don't need to use a FutureBuilder.

          – Ringil
          Nov 13 '18 at 21:17













          thanks but (await fetchResults(http.Client)); doesn't compile

          – flutter
          Nov 14 '18 at 11:24







          thanks but (await fetchResults(http.Client)); doesn't compile

          – flutter
          Nov 14 '18 at 11:24















          @user2387962 ah that was probably because it was inside setState... I edited it again

          – Ringil
          Nov 14 '18 at 12:50





          @user2387962 ah that was probably because it was inside setState... I edited it again

          – Ringil
          Nov 14 '18 at 12:50













          cheers works perfect

          – flutter
          Nov 14 '18 at 16:23





          cheers works perfect

          – flutter
          Nov 14 '18 at 16:23


















          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%2f53288493%2fhow-do-you-convert-a-list-future-to-a-list-to-use-as-a-variable-not-a-widget%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







          Popular posts from this blog

          The Sandy Post

          Danny Elfman

          Pages that link to "Head v. Amoskeag Manufacturing Co."