How to convert Future <List <Map> to list <Map> in Dart language?

I have a question about coding with dart language. How do I convert the future to a regular list? In my program, I need a result from the net to proceed with the next step, and I don't know how. In my case, I need to return the value of the "data" variables as a list.

class _MyAppState extends State<MyApp> {
    static List getList() {
    var url = "http://watcherman.cn/web/json.php";
    var data;
    HttpClient client = new HttpClient();
    client.getUrl(Uri.parse(url))
      .then((HttpClientRequest request) => request.close())
    .then((HttpClientResponse response) {
      response.transform(UTF8.decoder).listen((contents) {
        String jsonContent = contents.toString();
        data = JSON.decode(jsonContent);
      });
    });
    return data;
  }
}

      

But it looks like not doing the network part. Some of the flutter code doesn't seem to be able to accept the future.

class _MyAppState extends State<MyApp> {
  static List content = getList();
  @override
  Widget build(BuildContext context) {
    return new Container(
        child: new ListView.builder(
            scrollDirection: Axis.vertical,
            padding: new EdgeInsets.all(6.0),
            itemCount: content.length,
            itemBuilder: (BuildContext context, int index) {
              return new Container(
                  alignment: FractionalOffset.center,
                  margin: new EdgeInsets.only(bottom: 6.0),
                  padding: new EdgeInsets.all(6.0),
                  color: Colors.blueGrey,
                  child: new Text(content[index]["title"])
              );
            }
        )
    );
  }
}

      

+3


source to share


2 answers


You must rewrite your method getList

to return Future<List>

. It can be done with chaining then()

, but much more readable IMO for using / . async

await

Once you have a method that returns Future<List>

, you can use FutureBuilder

an asynchronous computation to build a tree that depends on the results.



screenshot

import 'package:flutter/material.dart';
import 'dart:io';
import 'dart:convert';
import 'dart:async';

void main() {
  runApp(new MaterialApp(
    home: new MyApp(),
  ));
}

class MyApp extends StatefulWidget {
  State createState() => new _MyAppState();
}

class _MyAppState extends State<MyApp> {

  static Future<List> getList() async {
    var url = "http://watcherman.cn/web/json.php";
    HttpClient client = new HttpClient();
    HttpClientRequest request = await client.getUrl(Uri.parse(url));
    HttpClientResponse response = await request.close();
    return response.transform(UTF8.decoder).transform(JSON.decoder).toList();
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Futures Demo'),
      ),
      body: new FutureBuilder(
        future: getList(),
        builder: (BuildContext context, AsyncSnapshot<List> snapshot) {
          if (!snapshot.hasData)
            return new Container();
          List content = snapshot.data[0];
          return new ListView.builder(
            scrollDirection: Axis.vertical,
            padding: new EdgeInsets.all(6.0),
            itemCount: content.length,
            itemBuilder: (BuildContext context, int index) {
              return new Container(
                alignment: FractionalOffset.center,
                margin: new EdgeInsets.only(bottom: 6.0),
                padding: new EdgeInsets.all(6.0),
                color: Colors.blueGrey,
                child: new Text('${content[index]['title']}'),
              );
            },
          );
        }
      )
    );
  }
}

      

+6


source


You cannot avoid asynchrony.

In Dart, a function returns a value or Future

. It returns the future when the result is not ready yet, when the function returns, it will only be available later.

This means you're stuck if all you have is this Future

and you want to get the value right now, because the value just doesn't exist yet. Now you cannot return List

, because Future<List>

now has no list, he has it later.



So, you must wait for this future, var data = await client.getUrl(...)...

which means that your function must be asynchronous as well. So, run getList

function a Future<List>

instead List

, because that's all it can do.

An alternative that Dart does not support would be a blocking operation that stops execution until a value is available and then resumes normal execution. This is a problem in a single threaded language (like Dart and JavaScript that Dart has to compile) as blocking means nothing happens and the UI becomes unresponsive.

So, if your result depends on the value of the future, your function should also be asynchronous and return its own result to the future.

+2


source







All Articles