How to Implement API Calls in Flutter? - http

I want to create a weather widget app by flutter but i am finding it difficult to do so as there is limited content on flutter. So if anyone knows how to Call , share your knowledge.

If you're building a weather widget you'll almost certainly want a location plugin, which doesn't exist yet but is coming soon.
Here is some code that shows current temperature in San Francisco.
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(
home: new MyHomePage(),
));
}
class Weather extends StatelessWidget {
final Map<String, dynamic> data;
Weather(this.data);
Widget build(BuildContext context) {
double temp = data['main']['temp'];
return new Text(
'${temp.toStringAsFixed(1)} °C',
style: Theme.of(context).textTheme.display4,
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePageState createState() => new MyHomePageState();
}
class MyHomePageState extends State<MyHomePage> {
Future<http.Response> _response;
void initState() {
super.initState();
_refresh();
}
void _refresh() {
setState(() {
_response = http.get(
'http://api.openweathermap.org/data/2.5/forecast'
'?q=San+Francisco&units=metric&APPID=14cc828bff4e71286219858975c3e89a'
);
});
}
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Weather Example"),
),
floatingActionButton: new FloatingActionButton(
child: new Icon(Icons.refresh),
onPressed: _refresh,
),
body: new Center(
child: new FutureBuilder(
future: _response,
builder: (BuildContext context, AsyncSnapshot<http.Response> response) {
if (!response.hasData)
return new Text('Loading...');
else if (response.data.statusCode != 200) {
return new Text('Could not connect to weather service.');
} else {
Map<String, dynamic> json = JSON.decode(response.data.body);
if (json['cod'] == 200)
return new Weather(json);
else
return new Text('Weather service error: $json.');
}
}
)
),
);
}
}

It could help someone, click here for official doc
1. Making Http Requests; import 'dart:io';
var httpClient = new HttpClient();
Create the client.
Construct the Uri.
Invoke the operation, and await the request object. Optionally,
configure the headers and body of the request.
Close the request, and await the response.
Decode the response
get() async {
var httpClient = new HttpClient();
var uri = new Uri.http(
'example.com', '/path1/path2', {'param1': '42', 'param2': 'foo'});
var request = await httpClient.getUrl(uri);
var response = await request.close();
var responseBody = await response.transform(UTF8.decoder).join();
Map data = JSON.decode(responseBody);
}

Related

Flutter code loops infinitely even after data is loaded from firebase

I am using the following Flutter and Firebase code to scaffold out a page to a user
import 'package:fgd6ss/models/user.dart';
import 'package:fgd6ss/screens/user/usr_type.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'dart:convert';
class UsertLanding extends StatefulWidget {
final Map code;
UserLanding({this.code});
User _user = User();
bool dataLoaded = false;
#override
_UserLandingState createState() => _UserLandingState();
}
class _UserLandingState extends State<UserLanding> {
#override
Widget build(BuildContext context) {
bool isValidUser = false;
dynamic userData;
Map codeData = widget.code;
try{
var document = FirebaseFirestore.instance.collection('users').where('id',isEqualTo: codeData['id']);
document.get().then((QuerySnapshot snapshot){
if (snapshot.docs.isNotEmpty) {
if (this.mounted) {
setState(() {
userData = snapshot.docs;
widget._user.name = userData[0]['name'];
widget._user.status = userData[0]['status'];
widget._user.type = userData[0]['type'];
print(widget._user.name);
});
}
}
});
}catch(e) {
print('error firebase data fetch');
}
return Scaffold(
backgroundColor: Color(0xfffefefe),
body: SafeArea(
child: Row(
children: <Widget>[
Container(
padding: EdgeInsets.all(20.0),
child: Text(
widget._user.name,
style: TextStyle(
fontSize: 22.0
),
),
)
]
)
)
);
}
}
As you can see from the above code, I have a print statement inside the query in try. When I run this code, I expect it to run once when the screen loads. But what happens is, the code keeps looping and prints out the users name again and again on the console. Is this expected? If not, what is causing this behaviour? If yes, will it cause increase in the document read quota count on Firebase end.
You have to create a separate method and call this method into your initState(). Build function is run continuously so your print statement is printed in the loop. So try with the below code. initState() method run only once when you reach on to the page
class UsertLanding extends StatefulWidget {
final Map code;
UserLanding({this.code});
User _user = User();
bool dataLoaded = false;
#override
_UserLandingState createState() => _UserLandingState();
}
class _UserLandingState extends State<UserLanding> {
bool isValidUser = false;
dynamic userData;
Map codeData;
#override
initState() {
super.initState();
codeData = widget.code;
getData();
}
getData() {
try {
var document = FirebaseFirestore.instance
.collection('users')
.where('id', isEqualTo: codeData['id']);
document.get().then((QuerySnapshot snapshot) {
if (snapshot.docs.isNotEmpty) {
if (this.mounted) {
setState(() {
userData = snapshot.docs;
widget._user.name = userData[0]['name'];
widget._user.status = userData[0]['status'];
widget._user.type = userData[0]['type'];
print(widget._user.name);
});
}
}
});
} catch (e) {
print('error firebase data fetch');
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xfffefefe),
body: SafeArea(
child: Row(children: <Widget>[
Container(
padding: EdgeInsets.all(20.0),
child: Text(
widget._user.name,
style: TextStyle(fontSize: 22.0),
),
)
])));
}
}
You are calling your function in the build method. So whenever the build method will be rebuilt or refreshed, it will call that function again and again. The better approach is to call it in your InitState so it will be called only once. Here is an example that might help you.
#override
initState() {
getData();
super.initState();
}

How do I pass data from one page to another?

I want to send the data to another page from come model data. Actually there are data on the getData function so model page, but when I send data to another page, data turn back as null. Can you please help me?
//model.dart
import 'dart:convert';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';
class Models {
var data;
Map jsondata = {};
var liste = new List();
Future<void> create(var table , data) async {
Firestore.instance.collection(table).document()
.setData(data).catchError((e){
print(e);
});
}
getData() async{
await Firestore.instance
.collection('musteri')
.document('-LgCmdigOCSqe9j-19lA')
.get()
.then((DocumentSnapshot datas) {
this.jsondata = datas.data;
});
return this.jsondata;
}
}
//chat.dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:chat/menu/bottomMenu.dart';
import 'package:chat/models/models.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class Chat extends StatelessWidget {
QuerySnapshot snapshot;
Models model = new Models();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Chat"),
centerTitle: true,
),
body: datas(),
bottomNavigationBar: BottomMenu(),
);
}
datas() {
model.getData();
print(model.jsondata);
}
}
When I use print( this.jsondata ) in the getData ,
result is { 'name':'jhon','surname':'wick' }
but model.jsondata is null in the chat.dart
your ui is built before the model data is populated.So you need to rebuild once you finish pulling in the data.
class Models {
var data;
Map jsondata = {};
var liste = new List();
Future<Map> getData() async{
return Firestore.instance
.collection('musteri')
.document('-LgCmdigOCSqe9j-19lA')
.get()
.then((DocumentSnapshot datas) => datas.data);
}
}
class Chat extends StatefulWidget {
#override
_ChatState createState() => _ChatState();
}
class _ChatState extends State<Chat> {
QuerySnapshot snapshot;
Models _model;
Map _jsondata;
#override
void initState() {
super.initState();
_model = new Models();
_model.getData().then((data) {
setState(() {
_jsondata = data;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Chat"),
centerTitle: true,
),
body: _jsondata == null
? Container()
: Container(
child: Center(
child: Text(
_jsondata["name"],
),
),
),
// bottomNavigationBar: BottomMenu(),
);
}
}
Try some thing like this.

Flutter refresh map after come back from second screen

I have a Flutter app which in home screen I use google map. At the begin, I call Firebase to take the places which I have already input. Then the user can add a new place if double in the map this lead him to SecondScreen. The user input title, story, and photo. I have and another screen where the user can view info for existing marker where can also delete it. My problem is when user input or delete marker and come back to the home page, in the map, the places are not refreshed and I see that the Firebase is not called again. How can I solve this problem? The Firebase is called in MapsDemo class
My code:
import 'dart:ui' as ui;
import 'dart:io';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:image_picker/image_picker.dart';
import 'package:uuid/uuid.dart';
import 'infopage.dart';
void main() {
GoogleMapController.init();
final size = MediaQueryData.fromWindow(ui.window).size;
final GoogleMapOverlayController controller =
GoogleMapOverlayController.fromSize(
width: size.width,
height: size.height,
);
final mapController = controller.mapController;
//// Set firebase https://www.youtube.com/watch?v=DqJ_KjFzL9I
//// TODO check if every time I come back the above commands call
// Firestore.instance.collection('Stories').snapshots().listen((data) =>
// data.documents.forEach((doc) =>
////Read all the markers from firebase and add them to map
//
// AddMarkers(mapController, ConvertCoordinates(doc["lat"], doc["lng"]),
// doc["title"], doc["story"], doc["url"])));
final Widget mapWidget = GoogleMapOverlay(controller: controller);
runApp(
MaterialApp(
home: new Scaffold(
appBar: AppBar(
title: TextField(
decoration: InputDecoration.collapsed(hintText: 'Search'),
),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.my_location),
onPressed: () async {
Position position = await Geolocator()
.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
// Get my current position
final location = LatLng(position.latitude, position.longitude);
mapController.markers.clear();
mapController.addMarker(MarkerOptions(
position: location,
infoWindowText: InfoWindowText("Here you are!", "Add me"),
visible: true));
mapController.animateCamera(
CameraUpdate.newLatLngZoom(location, 20.0),
);
},
),
],
),
body: MapsDemo(mapWidget, controller.mapController),
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: const Icon(Icons.my_location),
),
),
navigatorObservers: <NavigatorObserver>[controller.overlayController],
),
);
}
class MapsDemo extends StatelessWidget {
MapsDemo(this.mapWidget, this.controller);
final Widget mapWidget;
final GoogleMapController controller;
#override
Widget build(BuildContext context) {
// Set firebase https://www.youtube.com/watch?v=DqJ_KjFzL9I
// TODO check if every time I come back the above commands call
Firestore.instance.collection('Stories').snapshots().listen((data) =>
data.documents.forEach((doc) =>
//Read all the markers from firebase and add them to map
AddMarkers(controller, ConvertCoordinates(doc["lat"], doc["lng"]),
doc["title"], doc["story"], doc["url"])));
controller.onMarkerTapped.add((Marker marker) async {
//Marker listener open new page info page
String titlos = marker.options.infoWindowText.title;
if (titlos != "Here you are!") {
String story = marker.options.infoWindowText.snippet.split("?")[0];
String url = marker.options.infoWindowText.snippet.split("?")[1];
String realUrl = await makeRequest(url);
String downloadUrl =getDownloadUrl(realUrl,url);
Navigator.push(
// Parse title to next page/screen
context,
new MaterialPageRoute(
builder: (context) =>
new AboutPage(title: titlos, story: story, url: downloadUrl,)));
} else {
Navigator.push(
// Parse title to next page/screen
context,
new MaterialPageRoute(builder: (context) => new SecondScreen(
marker.options.position.latitude.toString(),
marker.options.position.longitude.toString())));
}
});
return Center(child: mapWidget);
}
}
LatLng ConvertCoordinates(String lat, String lng) {
// Convert strings coordinates to LatLng
return LatLng(double.parse(lat), double.parse(lng));
}
void AddMarkers(GoogleMapController map, LatLng coor, String title,
String story, String url) {
map.addMarker(MarkerOptions(
position: coor, infoWindowText: InfoWindowText(title, '$story'+'?'+'$url')));
}
Future<String> makeRequest(String n) async {
String baseUrl = 'https://firebasestorage.googleapis.com/v0/b/storymap-da000.appspot.com/o/';
String url = '$baseUrl' + '$n';
var client = new http.Client();
final response = await client.get(url);
return response.body;
}
String getDownloadUrl(String url, String name){
String baseUrl = 'https://firebasestorage.googleapis.com/v0/b/storymap-da000.appspot.com/o/';
String token = url.replaceAll("{", "").replaceAll("}", "").split('"downloadTokens": ')[1].replaceAll('"', '');
return '$baseUrl'+'$name'+"?alt=media&token="+'$token';
}
class SecondScreen extends StatelessWidget {
final String lat;
final String lng;
// final String image_name;
final titleC = TextEditingController();
final storyC = TextEditingController();
static final String image_name = Uuid().v1();
SecondScreen(this.lat, this.lng,);
Future getImage() async {
var image = await ImagePicker.pickImage(source: ImageSource.camera);
final StorageReference firebaseStorageRef =
FirebaseStorage.instance.ref().child(image_name);
final StorageUploadTask task =
firebaseStorageRef.putFile(image);
}
uploadFirebase(){
var map= {
"title":titleC.text,
"story":storyC.text,
"url":image_name,
"lat":lat,
"lng":lng
};
Firestore.instance.collection('Stories').document()
.setData(map);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Screen"),
),
body: Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new TextField (
controller: titleC,
),
new TextField(
controller: storyC,
),
new RaisedButton(
onPressed: () => getImage(),
child: new Text('Take photo'),
),
new RaisedButton(
onPressed: () => uploadFirebase(),
child: new Text('Confirm'),
)
])
),
);
}
}
[Edit]
I change my code to this,
import 'dart:ui' as ui;
import 'dart:io';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:image_picker/image_picker.dart';
import 'package:uuid/uuid.dart';
import 'infopage.dart';
void main() {
GoogleMapController.init();
final size = MediaQueryData.fromWindow(ui.window).size;
final GoogleMapOverlayController controller =
GoogleMapOverlayController.fromSize(
width: size.width,
height: size.height,
);
final mapController = controller.mapController;
//// Set firebase https://www.youtube.com/watch?v=DqJ_KjFzL9I
//// TODO check if every time I come back the above commands call
// Firestore.instance.collection('Stories').snapshots().listen((data) =>
// data.documents.forEach((doc) =>
////Read all the markers from firebase and add them to map
//
// AddMarkers(mapController, ConvertCoordinates(doc["lat"], doc["lng"]),
// doc["title"], doc["story"], doc["url"])));
final Widget mapWidget = GoogleMapOverlay(controller: controller);
runApp(
MaterialApp(
home: new Scaffold(
appBar: AppBar(
title: TextField(
decoration: InputDecoration.collapsed(hintText: 'Search'),
),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.my_location),
onPressed: () async {
Position position = await Geolocator()
.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
// Get my current position
final location = LatLng(position.latitude, position.longitude);
mapController.markers.clear();
mapController.addMarker(MarkerOptions(
position: location,
infoWindowText: InfoWindowText("Here you are!", "Add me"),
visible: true,draggable: true));
mapController.animateCamera(
CameraUpdate.newLatLngZoom(location, 20.0),
);
},
),
IconButton(
icon: const Icon(Icons.refresh),
onPressed: () {RefreshIt(mapController);},
)
],
),
body: _MapDemo(mapWidget:mapWidget, controller:controller.mapController),
),
navigatorObservers: <NavigatorObserver>[controller.overlayController],
),
);
}
class _MapDemo extends StatefulWidget{
final Widget mapWidget;
final GoogleMapController controller;
const _MapDemo({Key key, this.mapWidget, this.controller}) : super(key: key);
#override
MapsDemo createState() => MapsDemo(this.mapWidget, this.controller);
}
class MapsDemo extends State<_MapDemo> {
MapsDemo(this.mapWidget, this.controller);
final Widget mapWidget;
final GoogleMapController controller;
#override
Widget build(BuildContext context) {
// Set firebase https://www.youtube.com/watch?v=DqJ_KjFzL9I
controller.markers.clear();
// TODO check if every time I come back the above commands call
Firestore.instance.collection('Stories').snapshots().listen((data) =>
data.documents.forEach((doc) =>
//Read all the markers from firebase and add them to map
AddMarkers(controller, ConvertCoordinates(doc["lat"], doc["lng"]),
doc["title"], doc["story"], doc["url"])));
controller.onMarkerTapped.add((Marker marker) async {
//Marker listener open new page info page
String titlos = marker.options.infoWindowText.title;
if (titlos != "Here you are!") {
String story = marker.options.infoWindowText.snippet.split("?")[0];
String url = marker.options.infoWindowText.snippet.split("?")[1];
String realUrl = await makeRequest(url);
String downloadUrl =getDownloadUrl(realUrl,url);
Navigator.push(
// Parse title to next page/screen
context,
new MaterialPageRoute(
builder: (context) =>
new AboutPage(title: titlos, story: story, url: downloadUrl,)));
} else {
Navigator.push(
// Parse title to next page/screen
context,
new MaterialPageRoute(builder: (context) => new _SecondScreen(
lat:marker.options.position.latitude.toString(),
lng:marker.options.position.longitude.toString())));
}
});
return Center(child: mapWidget);
}
}
LatLng ConvertCoordinates(String lat, String lng) {
// Convert strings coordinates to LatLng
return LatLng(double.parse(lat), double.parse(lng));
}
void AddMarkers(GoogleMapController map, LatLng coor, String title,
String story, String url) {
map.addMarker(MarkerOptions(
position: coor, infoWindowText: InfoWindowText(title, '$story'+'?'+'$url')));
}
void RefreshIt(GoogleMapController mapController){
//TODO Refresh the map via this float button
}
Future<String> makeRequest(String n) async {
String baseUrl = 'https://firebasestorage.googleapis.com/v0/b/storymap-da000.appspot.com/o/';
String url = '$baseUrl' + '$n';
var client = new http.Client();
final response = await client.get(url);
return response.body;
}
String getDownloadUrl(String url, String name){
String baseUrl = 'https://firebasestorage.googleapis.com/v0/b/storymap-da000.appspot.com/o/';
String token = url.replaceAll("{", "").replaceAll("}", "").split('"downloadTokens": ')[1].replaceAll('"', '');
return '$baseUrl'+'$name'+"?alt=media&token="+'$token';
}
class _SecondScreen extends StatefulWidget{
final String lat;
final String lng;
const _SecondScreen({Key key, this.lat, this.lng}) : super(key: key);
#override
SecondScreen createState() => SecondScreen(this.lat, this.lng);
}
class SecondScreen extends State<_SecondScreen> {
final String lat;
final String lng;
// final String image_name;
final titleC = TextEditingController();
final storyC = TextEditingController();
static final String image_name = Uuid().v1();
SecondScreen(this.lat, this.lng,);
Future getImage() async {
var image = await ImagePicker.pickImage(source: ImageSource.camera);
final StorageReference firebaseStorageRef =
FirebaseStorage.instance.ref().child(image_name);
final StorageUploadTask task =
firebaseStorageRef.putFile(image);
}
uploadFirebase(){
var map= {
"title":titleC.text,
"story":storyC.text,
"url":image_name,
"lat":lat,
"lng":lng
};
Firestore.instance.collection('Stories').document()
.setData(map);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Input Screen"),
),
body: Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new TextField (
controller: titleC,
),
new TextField(
controller: storyC,
),
new RaisedButton(
onPressed: () => getImage(),
child: new Text('Take photo'),
),
new RaisedButton(
onPressed: () => uploadFirebase(),
child: new Text('Confirm'),
)
])
),
);
}
}
My firebase is shared with a website with the same concept, when I add something in the website the new marker is appeared in my Flutter app, but not when I delete a marker. On the other hand, when I add or remove marker from my Flutter app I don't get any refresh in my map... Any idea?
I set the mapStyle after resuming app from background and it worked for me:
mapController.setMapStyle("[]");
All of your widgets are Stateless which means they won't be able to update or change upon user interaction. This tutorial from the Flutter documentation goes through how to add interactivity to your app using Stateful widgets which will solve your problem.

Firestore async load and populate listview flutter

Hi i am trying to get data from firestore and populate listview, following is my code, but i am getting exception since my async call is not complete how can i wait for that asyn call to get completed and populate my listview
my code is below:
import 'dart:async';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:test_flutter/pkg/Feed.dart';
class FeedLoader {
final CollectionReference _colReference;
FeedLoader(Firestore _firestore)
: _colReference = _firestore.collection(Feed.getDocumentName()) {}
Future<List<Feed>> load() async {
final List<Feed> feeds = new List<Feed>();
await for (QuerySnapshot qs in _colReference.snapshots) {
for (DocumentSnapshot ds in qs.documents) {
feeds.add(Feed.fromJson(ds.data));
}
return feeds;
}
return feeds;
}
}
This is my Widget
import 'package:flutter/material.dart';
import 'package:test_flutter/pkg/FeedLoader.dart';
import 'package:test_flutter/pkg/Feed.dart';
class FeedWidget extends StatefulWidget {
final FeedLoader feedLoader;
const FeedWidget({Key key, this.feedLoader}) : super(key: key);
createState() => new FeedWidgetState(feedLoader);
}
class FeedWidgetState extends State<FeedWidget> {
final List<Feed> _feeds = new List<Feed>();
final FeedLoader _feedLoader;
final TextStyle fontStyle = const TextStyle(fontSize: 16.0);
FeedWidgetState(this._feedLoader);
#override
Widget build(BuildContext context) {
print(_feedLoader == null);
_feedLoader
.load()
.then((feeds) => () {
print("Got call back now");
_feeds.addAll(feeds);
})
.catchError((e) => handleError(e));
print("Feeds size ${_feeds}");
return _buildListView(context);
}
void handleError(e) {
print("FeedLoaderException ${e}");
}
Widget _buildListView(BuildContext context) {
return new ListView.builder(
padding: const EdgeInsets.all(6.0),
itemBuilder: (context, i) {
if (i.isOdd) return new Divider();
final index = i ~/ 2;
// pagination
// if (index >= contents.length) {
// contents.addAll(generateWordPairs().take(10));
// }
return _buildRowContent(context, _feeds[i]);
},
);
}
Widget _buildRowContent(BuildContext context, Feed content) {
return new ListTile(
title: new Text(
"${content.getTitle()}",
style: fontStyle,
),
);
}
}
You can use StreamBuilder and FutureBuilder to build widgets asynchronously
You could for example do
return new StreamBuilder(
stream: Firestore....snapshot,
builder: (context, snapshot) {
if (snapshot.hasData) {
final feeds = snapshot.data.map(Feed.fromJson);
return new ListView(
....
);
}
},
)

not able to update list after http call ( flutter)

i'm new to flutter
i try to do an http call and then populate a list. The problem is that the http call works fine but the UI doesn't refresh.
i think that the problem is that the framework create ui with the list before the http call is finish. Than when the http call is finished i'm unable to update the ui.
i've search but i didn't find anything.
EDIT--FOUND SOLUTION IN Listview.Builder code here
http call
static Future<Map> getData() async {
try{
http.Response res = await http.get("http://....");
Map data = JSON.decode(res.body);
print(res.body);
return data;
}
catch(exception){
//todo
}
}
main
class _MyHomePageState extends State<MyHomePage> {
List<Widget> _items = new List<GithubCardItem>();
#override
void initState() {
super.initState();
print("start download");
_downloadData();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text(widget.title)),
body: new ListView.builder(
itemBuilder: (BuildContext context, int index) => _items[index],
itemExtent: 128.0,
itemCount: _items.length,
),
floatingActionButton: new FloatingActionButton(
child: new Icon(Icons.add),
onPressed: (){
_downloadData();
},
)
);
}
GithubCard _extractDataFromJson(Map githubCard){
GithubCard card = new GithubCard(githubCard["name"], githubCard["avatar_url"], githubCard["description"], githubCard["stargazers_count"], githubCard["open_issued_count"]);
return card;
}
void _downloadData(){
MyHttpCall.getData().then((jsonData) {
//check if i have card to display
if(jsonData["items"] != null){
for(var githubCard in jsonData["items"]){
setState(() {
GithubCard card = _extractDataFromJson(githubCard);
this._items.add(new GithubCardItem(card));
});
print("adding elements");
}
}
});
}
}
the GithubCardItem is a simple stateless widget that return a text.
There are different ways to use ListView as well as get data from network
here is the sample code for your problem
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List list = new List();
void fetchData() {
getData().then((res) {
setState(() {
list.addAll(res);
});
});
}
#override
void initState() {
super.initState();
fetchData();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new ListView.builder(
itemCount: list.length,
itemBuilder: ((BuildContext _context, int position) {
return new ListTile(
title: new Text( list[position]['login'].toString()),
subtitle: new Text(list[position]['url']),
leading: new Image.network(list[position]['avatar_url']),
);
}),
),
),
floatingActionButton: new FloatingActionButton(
onPressed: fetchData,
tooltip: 'Increment',
child: new Icon(Icons.add),
),
);
}
Future<List> getData() async {
var url = "https://api.github.com/users";
List data = new List();
var httpClient = new HttpClient();
var request = await httpClient.getUrl(Uri.parse(url));
var response = await request.close();
if (response.statusCode == HttpStatus.OK) {
var jsonString = await response.transform(utf8.decoder).join();
data = json.decode(jsonString);
return data;
}else{
return data;
}
}
}
Try this:
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {----------- }
class MyHomePage extends StatefulWidget {-----------}
class _MyHomePageState extends State<MyHomePage> {
List data;
Future<String> getData() async {
var response = await http.get(
Uri.encodeFull("https://api.github.com/users"),
headers: {"Accept": "application/json"});
this.setState(() {
data = json.decode(response.body);
});
return "Success!";
}
#override
void initState() {
this.getData();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Listviews"),
),
body: new ListView.builder(
itemCount: data == null ? 0 : data.length,
itemBuilder: (BuildContext context, int position) {
return new ListTile(
title: new Text(data[position]['login'].toString()),
subtitle: new Text(data[position]['url']),
leading: new Image.network(data[position]['avatar_url']),
);
},
),
);
}
}
Made bit more simple and it's working. Check the sample here

Resources