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.
Related
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();
}
i wil put all the code below this explanation
so i just create a CollectionReference like this
in class DataBaseServices
final CollectionReference brewCollection =
Firestore.instance.collection('brews');
and i add data normally
after i use it in stream
Stream<QuerySnapshot> get brews {
return brewCollection.snapshots();
}
and i put the value in widget
Widget build(BuildContext context) {
return StreamProvider<QuerySnapshot>.value(
value: DataBaseServices().brews,
and in another widget
i call it
final snapshot = Provider.of<QuerySnapshot>(context);
and after i check here if it is null i find that it is null
the code :
class database
import 'package:cloud_firestore/cloud_firestore.dart';
class DataBaseServices {
final CollectionReference brewCollection =
Firestore.instance.collection('brews');
final String uid;
DataBaseServices({this.uid});
Future updateUserData({int sugar, String name, int strength}) async {
return await brewCollection.document(uid).setData(
{'sugar': sugar, 'name': name, 'strength': strength},
);
}
Stream<QuerySnapshot> get brews {
return brewCollection.snapshots();
}
}
home class
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:crewbrewapp/screens/home/brews_list.dart';
import 'package:crewbrewapp/services/auth.dart';
import 'package:crewbrewapp/services/database.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
AuthServices _auth = AuthServices();
#override
Widget build(BuildContext context) {
return StreamProvider<QuerySnapshot>.value(
value: DataBaseServices().brews,
child: Scaffold(
backgroundColor: Colors.brown.shade100,
appBar: AppBar(
title: Text('Home'),
centerTitle: true,
backgroundColor: Colors.brown.shade500,
actions: <Widget>[
FlatButton.icon(
icon: Icon(Icons.person),
label: Text('Log out'),
onPressed: () async {
await _auth.signOut();
},
),
],
leading: Icon(Icons.menu),
),
body: BrewsList(),
),
);
}
}
class brewList
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:crewbrewapp/screens/home/brew_tile.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:crewbrewapp/models/brew.dart';
class BrewsList extends StatefulWidget {
#override
_BrewsListState createState() => _BrewsListState();
}
class _BrewsListState extends State<BrewsList> {
List<Brew> brews;
#override
Widget build(BuildContext context) {
final snapshot = Provider.of<QuerySnapshot>(context);
if (snapshot != null) {
snapshot.documents.map(
(element) {
brews = [
Brew(
sugar: element.data['sugar'] ?? 0,
strength: element.data['strength'] ?? 0,
name: element.data['name'] ?? '',
),
];
},
);
}
return brews == null
? Container(
child: Text('Empty'),
)
: ListView.builder(
itemCount: brews.length,
itemBuilder: (context, index) {
return BrewTile(brew: brews[index]);
},
);
}
}
i tried everything but it still show nothing
Rather you should assign brews to the whole map:
if (snapshot != null) {
brews = snapshot.documents.map(
(element) {
return Brew(
sugar: element.data['sugar'] ?? 0,
strength: element.data['strength'] ?? 0,
name: element.data['name'] ?? '',
);
},
).toList();
}
I believe your snapshot is not quite created by the time it is called in brewList.
A progress indicator may work for you;
if (snapshot == null) return CircularProgressIndicator();
snapshot.documents.map(
(element) {
brews = [
Brew(
sugar: element.data['sugar'] ?? 0,
strength: element.data['strength'] ?? 0,
name: element.data['name'] ?? '',
),
];
);
}
add if
call doc.data() - data with () operator ,see below code in the class BrewList:
final brews = Provider.of<QuerySnapshot>(context);
//print(brews);
if (brews != null) {
for (var doc in brews.docs) {
print(doc.data());
}
}
call BrewList() class with provider from Home class,
see below code in the class Home :
> return StreamProvider<QuerySnapshot>.value(
> initialData: null,
> value: DatabaseBrews(uid:'').brews,
> child: Scaffold(...
> body: BrewList(),)
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(
....
);
}
},
)
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
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);
}