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"])
);
}
)
);
}
}
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.
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']}'),
);
},
);
}
)
);
}
}
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.