Marks needing to build error shown with the StreamProvider widget - flutter-provider

I got the error message with the following code that I was trying to use a StreamProvider on the buildContext, I have already added 'listen: false' in the initState process. Any idea how to change the code? Any where exactly was the problem?
#override
void initState() {
final gameProvider = Provider.of<GameProvider>(context,listen :false);
gameProvider.changeGameId = widget.game.gameId;
super.initState();
}
#override
Widget build(BuildContext context) {
final gameProvider = Provider.of<GameProvider>(context);
// gameProvider.changeGameId = widget.game.gameId;
if (gameProvider == null) return Container();
return Scaffold(
appBar: AppBar(
title: Text('OnLine BlackJack'),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Stack(
children: [
Positioned(
top: 420,
left: 1,
height: 180,
width: 99, //+ gameProvider.playerHandJson.length * 30,
//duration: Duration(seconds: 1),
child: Container(
child: gameProvider.playerHandJson != null
? HandJsonDecode(handJson: gameProvider.playerHandJson)
: Container(),
)),

If you can show your GameProvider, will help us to understand better the problem.
Also i think you are calling a function changeGameId as a variable.
gameProvider.changeGameId = widget.game.gameId;
gameProvider.changeGameId(widget.game.gameId);
I suppouse you have somtihing like this in your provider
class GameProvide extend ChangeNotifier{
final _gameId;
void function changeGameId(String id){
_gameId = id;
notifyListeners();
}
}

I have resolved the problme by using the StreamBuilder, but not why the changeGameId was causing the error. I did have the changeGameId function coded in the GameProvider class.
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('OnLine BlackJack'),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Stack(
children: [
StreamBuilder<Game>(
stream: firestoreService.joinedGame(widget.game.gameId),
builder: (context, snapshot) {
var game = snapshot.data;
if (game != null) {
return Stack(children: [
Positioned(
top: 1,
left: 1,
width: (game.playerHandJson.length) * 30.0 + 69,
height: 180,
child: Container(
child: HandJsonDecode(
handJson: game.playerHandJson,
))),

Related

how to reduce number of reads in firebase?

i have created a chat app and everything works fine except two things
1- in fire base store i get too much reads even if i do nothing, for example i just used my chat app for 5 minuets i got around 6000 reads
2- when i chat to any person some messages don't get received, this is an example
the other person(wiliam) did not receive three messages( yeah, k , now).
///////////
this is the stream builder code to display messages
class Streambuild extends StatelessWidget {
final String roomid;
Streambuild({#required this.roomid});
#override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: _store
.collection('FCHATROOM')
.doc(roomid)
.collection("CHAT")
.orderBy('time', descending: true)
.snapshots(),
builder: (context, snap) {
if (!snap.hasData) {
return Center(
child: Text('No Messages'),
);
}
return Expanded(
child: ListView.builder(
itemCount: snap.data.docs.length,
reverse: true,
shrinkWrap: true,
itemBuilder: (context, index) {
return Bubblemsg(
txt: snap.data.docs[index].data()['message'],
sender: snap.data.docs[index].data()['sender'],
realtime: snap.data.docs[index].data()['realtime'],
isMe: (snap.data.docs[index].data()['sender'] ==
_auth.currentUser.email),
);
}),
);
});
}
}
bubble message code:
class Bubblemsg extends StatelessWidget {
Bubblemsg({this.sender, this.txt, this.isMe, this.realtime});
final String txt;
final String sender;
final bool isMe;
final String realtime;
#override
Widget build(BuildContext context) {
var myprov = Provider.of<Help>(context, listen: false);
return Container(
width: double.infinity,
child: Bubble(
elevation: 5,
padding: BubbleEdges.all(10),
margin: isMe
? BubbleEdges.only(top: 10, right: 5, left: 30)
: BubbleEdges.only(top: 10, left: 5, right: 30),
alignment: isMe ? Alignment.topRight : Alignment.topLeft,
nip: isMe ? BubbleNip.rightTop : BubbleNip.leftTop,
color: isMe ? myprov.mid : Colors.grey[900],
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
txt != null
? txt.startsWith("https://firebasestorage.googleapis.com/v0")
? Imagecontainer(
url: txt,
)
: SelectableText(
txt != null ? txt : "",
style: TextStyle(
color: myprov.word,
fontSize: 20,
),
)
: Text(""),
Padding(
padding: EdgeInsets.only(top: 10.0),
child: Text(
realtime != null ? realtime : "",
style: TextStyle(fontSize: 15, color: myprov.word),
textAlign: TextAlign.end,
),
)
],
),
),
);
}
}

Flutter/Dart/Firebase - wait until data has loaded before displaying

I am trying to create a list of unique "events" in my app. I have created a couple of functions to extract the data from firebase:
// event list from snapshot
List<String> _eventsFromSnapshot(QuerySnapshot snapshot) {
return snapshot.docs.map(
(doc) {
return doc['event'].toString() ?? '';
},
).toList();
}
//get events data
Stream<List<String>> get events {
return productCollection.snapshots().map(_eventsFromSnapshot);
}
I then want to build my list view in another screen. I have implemented my StreamProvider in the root page of my homescreen:
class OurHomePage extends StatefulWidget {
#override
_OurHomePageState createState() => _OurHomePageState();
}
class _OurHomePageState extends State<OurHomePage> {
#override
Widget build(BuildContext context) {
return StreamProvider<List<Product>>.value(
value: OurDatabase().products.handleError((e) {
print(e.toString());
}),
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Align(
alignment: Alignment.center,
child: Column(
children: [
OurHeadline(),
AllCards(),
HowItWorks(),
],
),
),
),
),
);
}
}
And then I create a function to return the list of Strings and use that in my stateless widget:
class AllCards extends StatelessWidget {
#override
Widget build(BuildContext context) {
final List<String> uniqueEventList = getListOfEvents(context);
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [Text('Browse all Cards'), Text('Shop All')],
mainAxisAlignment: MainAxisAlignment.spaceBetween,
),
SizedBox(
height: 125,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: uniqueEventList.length,
itemBuilder: (context, i) {
return Container(
decoration: BoxDecoration(
border: Border.all(),
),
width: 160.0,
child: Center(
child: Text(uniqueEventList[i]),
),
);
},
),
)
],
),
),
);
}
List<String> getListOfEvents(BuildContext context) {
final uniqueEvents = Provider.of<List<Product>>(context);
final List<String> list = [];
for (var item in uniqueEvents) {
list.add(item.event);
}
return list.toSet().toList();
}
}
The problem is that whenever I switch pages, for a split second I get this message and an error appears:
The getter 'iterator' was called on null.
Receiver: null
Tried calling: iterator
Which indicates to me that I need to use some sort of async functionality to wait for the events data to finish loading, but is there a simple way to do this without going for something like a Future builder?
Any help would be appreciated!

Flutter/Dart - type 'List<DropdownMenuItem<dynamic>>' is not a subtype of type 'List<DropdownMenuItem<String>>

I am trying to create a drop down list inside an alert dialog widget. The menu items need to be pulled from firebase. So far, I have created my alert dialog, looped through my firebase data and created a list from the results. The issue I am facing comes when I try to use my list as the "items" for my dropdown, when I run my code I get the following error:
type 'List<DropdownMenuItem<dynamic>>' is not a subtype of type 'List<DropdownMenuItem<String>>'
Here is my code:
class ViewSingleCard extends StatefulWidget {
final String imgUrl;
final String message;
ViewSingleCard({this.imgUrl, this.message});
#override
_ViewSingleCardState createState() => _ViewSingleCardState(imgUrl, message);
}
class _ViewSingleCardState extends State<ViewSingleCard> {
String imgUrl;
String message;
_ViewSingleCardState(this.imgUrl, this.message);
PageController _pageController = PageController(initialPage: 0);
int currentPage = 0;
#override
void dispose() {
super.dispose();
_pageController.dispose();
}
_onPageChanged(int index) {
setState(() {
currentPage = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.deepPurpleAccent,
title: Text('Viewer'),
actions: [
Stack(
children: [
IconButton(
icon: Icon(Icons.add),
onPressed: () {
createAlertDiaglog(context);
})
],
)
],
),
body: Stack(
alignment: AlignmentDirectional.bottomCenter,
children: <Widget>[
PageView(
scrollDirection: Axis.horizontal,
controller: _pageController,
onPageChanged: _onPageChanged,
children: [
Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Image(
image: FirebaseImage(imgUrl,
maxSizeBytes: 15 * 1024 * 1024))),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Text(message),
),
),
],
),
Stack(
children: <Widget>[
Container(
margin: const EdgeInsets.only(bottom: 35),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
for (int i = 0; i <= 1; i++)
if (i == currentPage)
SlideDots(true)
else
SlideDots(false)
],
),
),
],
),
]),
);
}
createAlertDiaglog(BuildContext context) {
String selectedOccasion;
List<DropdownMenuItem> occasions = [];
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text("Add to collection"),
content: StreamBuilder<QuerySnapshot>(
stream: getCollectionInfo(context),
// ignore: missing_return
builder: (context, snapshot) {
if (!snapshot.hasData)
const Text("Loading.....");
else {
for (int i = 0; i < snapshot.data.docs.length; i++) {
DocumentSnapshot snap = snapshot.data.docs[i];
occasions.add(
DropdownMenuItem(
child: Text(
snap.id,
),
value: "${snap.id}",
),
);
}
}
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// ignore: missing_return
DropdownButton<String>(
items: occasions,
hint: Text("Style"),
value: selectedOccasion,
onChanged: (String Value) {
setState(() {
selectedOccasion = Value;
});
},
),
],
);
}),
);
});
}
Stream<QuerySnapshot> getCollectionInfo(BuildContext context) async* {
yield* FirebaseFirestore.instance
.collection('collections')
.doc(FirebaseAuth.instance.currentUser.uid)
.collection('occasions')
.snapshots();
}
}
Any help? Thanks
Here's the fix, add the <String> there:
occasions.add(
DropdownMenuItem<String>(
child: Text(
and also fix the type of the list (thanks to #nvoigt's answer)
List<DropdownMenuItem<String>> occasions = [];
Your DropDownButton is given the <String> type, so it's expecting the same thing from its items.
Whenever you get this exception, just swap the locations of the two types and think of an assignment. This means you are trying to do this kind of assignment
List<DropdownMenuItem<String>> a;
List<DropdownMenuItem<dynamic>> b;
a = b;
This:
List<DropdownMenuItem> occasions = [];
is a List<DropdownMenuItem<dynamic>>, but you want a List<DropdownMenuItem<String>>, so you need to make it one:
List<DropdownMenuItem<String>> occasions = [];
That said: you have an analyzer. Do not ignore it's warnings. You have ignored warnings that are correct, where you have made a mistake. Do not do this. Do not ignore your mistakes, fix them.

Want to pass the total price in the bottom navigation bar in flutter

How can i show the total amount in the bottom navigation bar... The app uses firebase backend... I have a filed in my database name total price of each item... Now I want to fetch the total price of each item and then add it and display in the bottom navigation bar..
I have attach my firebase backend screen shot.. what i need is to get all the value of the field 'total' add it up and show it in the bottom bar below the Total which is hardcoded as 999 currently section...
It would be helpful if some let me know how to do it.. I am new to app development and flutter as well
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/foundation.dart';
import 'dart:async';
import 'package:fluttertoast/fluttertoast.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final myController = TextEditingController(); ///Alert Dialog box input text myController will be use to store the number of qty
String id;
var qty;
var price;
var total;
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home:Scaffold(
bottomNavigationBar: new Container( //// Bottom Naviagtion Bar for check out and Total price
color: Colors.white,
child: Row(
children: <Widget>[
Expanded(child: ListTile(
title: Text("Total"),
subtitle: Text("Rs 999"),
),),
Expanded(
child: MaterialButton(onPressed:() {},
child: Text("Check Out",style: TextStyle(color: Colors.white),),
color: Colors.red,) ,
)
],
),
),
appBar: AppBar(title: Text('MyKart'),
),
body: (
StreamBuilder(
stream: Firestore.instance.collection('KartDetails').snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
DocumentSnapshot kartDetails = snapshot.data.documents[index];
return Container(
height: 150,
child: Card(
elevation: 10,
child: Container(
height: 100,
width: 100,
child: Row(
children: <Widget>[
Container(
width: 100,
height: 100,
child: Image.network(kartDetails['img']),
),
Container(
child: (Text(kartDetails['item'])),
),
Container(
width: 50,
child: (Text('Rs '+kartDetails['price'].toString(),textAlign: TextAlign.end,)),
),
Container(
margin: EdgeInsets.only(left: 20),
height: 120,
width: 50,
color: Colors.white10,
child: Column(
children: <Widget>[
RaisedButton(
color: Colors.grey,
onPressed: (){
showDialog(context: context,
builder: (BuildContext context){
return Dialog(
child: Container(
height: 250,
color: Colors.white10,
child: Container(
margin: EdgeInsets.all(40.0),
child: Column(
children: <Widget>[
TextField(
controller: myController,
keyboardType: TextInputType.number,
decoration: InputDecoration(hintText: 'Enter the Quantity'),
),
Container(
height: 50,
),
RaisedButton(
color: Colors.blue,
child: Text('Submit'),
onPressed: () async{
qty = myController.text;
//==================================================================Total Number of QTY ENTERED==========================================//
if (int.parse(qty)>0 && int.parse(qty)>=5) {
CollectionReference collectionRefernce = Firestore
.instance.collection(
'KartDetails');
QuerySnapshot querySnapshot = await collectionRefernce
.getDocuments();
querySnapshot
.documents[index]
.reference
.updateData(
{"quantity": qty});
//==================================================================Calculate price for each product==========================================//
price = kartDetails['price'];
total=int.parse(qty)*price;
querySnapshot
.documents[index]
.reference
.updateData(
{"total": total});
print(myController
.toString());
Navigator.of(context)
.pop();
myController.clear();
Fluttertoast.showToast(msg: "Quantity Updated",
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 20.0
);
}
else if(int.parse(qty) < 5 || int.parse(qty)<0) {
Fluttertoast.showToast(msg: "Minimum 5 quanity",
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 20.0
);
myController.clear();
}
else {
Fluttertoast.showToast(msg: "Please enter valid quantity",
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 20.0
);
myController.clear();
}
//Firebase query
},
)
],
),
),
),
);
});
},
child: Icon(Icons.shopping_basket),
),
Container(
height: 20,
),
RaisedButton(
color: Colors.grey,
child: Icon(Icons.delete,color: Colors.black87,),
)
],
),
),
Column(
children: <Widget>[
Container(
margin: EdgeInsets.only(left: 3),
height: 50,
width: 70,
child: Center(child: Text('Quantity')),
),
Container(
width: 70,
child: Center(child: Text((kartDetails['quantity']).toString())),
),
Container(
margin: EdgeInsets.only(top: 25),
child: Center(child: Text('Total Price')),),
Container(
margin: EdgeInsets.only(left: 3),
width: 70,
child: Center(child: Text(("Rs " + (kartDetails['total']).toString()))),
),
],
),
],
),
),
),
);
},
);
}
else{
return Center(
child: Container(),
);;
}
},
)
),
),
);
}
}
You can easily do it with this method:
var totalCartValue = 0;
String getCartTotal() async {
QuerySnapshot snapshot = await Firestore.instance
.collection('KartDetails')
.getDocuments();
snapshot.documents.forEach((doc) {
setState((){
totalCartValue += doc.data['total'];
});
});
return totalCartValue.toString();
}
P.S: This method will give you the total of all values in the KartDetails collection not the total for the current user, for the current user it should be like this:
var totalCartValue = 0;
String getCartTotal() async {
QuerySnapshot snapshot = await Firestore.instance
.collection('KartDetails')
.where("UID", isEqualTo: FirebaseAuth.instance.currentUser().toString())
.getDocuments();
snapshot.documents.forEach((doc) {
setState((){
totalCartValue += doc.data['total'];
});
});
return totalCartValue.toString();
}
And use it in the UI that way:
class YourClassName extends StatefulWidget {
#override
_YourClassNameState createState() => _YourClassNameState();
}
class _YourClassNameState extends State<YourClassName> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: //your body code,
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(
icon: new Icon(Icons.cart_shopping),
title: new Text(totalCartValue),
),
]
)
);
}
}
You should call it inside your initState so it gets executed whenever app starts:
#override
initState(){
super.initState();
getCartTotal();
}
This is a very vague question, so I will give a shot at one method of solving this. In order to do this you will need some sort of state management solution. I suggest using provider. Flutter has a tutorial on provider here. Essentially you will have to create a ChangeNotifier that every time would onAddItem and onDeleteItem and call notifyListeners() whenever you add or delete items. Then your bottom bar would simply use a Consumer to get the values from your ChangeNotifier. As I said this is just one approach, but since you did not give a replicable example this is the best I can do.

Value is retrieved only after hot reload in flutter

I'm kinda new to flutter, I've been building a small app using firebase as the backend, whenever I try to load data from firebase I'm not able to fetch the value until I reload the app, this isn't the entire code,
I think the widgets are loading before the data itself, could really use ur help, is there any way that I could use the state to refresh the value?
mycode:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import "package:flutter/material.dart";
import 'package:mine_app/textingpage.dart';
class FriendsPage extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _FriendsPage();
}
}
class Friends {
final int theirTexts;
final String username;
final int myTexts;
final int totalTexts;
final String friendId;
Friends(this.theirTexts,this.totalTexts,this.username,this.myTexts,this.friendId);
Friends.fromMap(DocumentSnapshot map)
:assert(map["username"]!=null),
assert(map["myTexts"]!=null),
assert(map["theirTexts"]!=null),
assert(map["totalTexts"]!=null),
assert(map["uid"]!=null),
username = map["username"],
myTexts = map["myTexts"],
theirTexts = map["theirTexts"],
totalTexts = map["totalTexts"],
friendId = map["uid"];
}
class _FriendsPage extends State<FriendsPage> {
String user;
String globalid = "";
Future<void> getuser() async {
user = (await FirebaseAuth.instance.currentUser()).uid;
}
#override
void initState() {
getuser();
super.initState();
}
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
backgroundColor: Color(0xff723881),
centerTitle: true,
title: Text(
"Chats",
bottom: TabBar(
tabs: [
Tab(icon: Icon(Icons.people), text: "People"),
Tab(icon: Icon(Icons.search), text: "Find"),
],
indicatorColor: Colors.white,
),
),
body: TabBarView(
children: <Widget>[
Container(
child: snapShotBuilder(context)
),
Container()
],
)),
);
}
Widget snapShotBuilder(BuildContext context){
return StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection("users").document(user).collection("friends").snapshots(),
builder:(context,snapshot){
if (!snapshot.hasData) {
return LinearProgressIndicator();
}
return myListView(context,snapshot.data.documents);
} );
}
Widget myListView(BuildContext context,List<DocumentSnapshot> snapshot){
return Container(
child: ListView(
children: snapshot.map((data)=>myfriends(Friends.fromMap(data))).toList(),
),
);
}
Widget myfriends(Friends friend) {
return Container(
margin: EdgeInsets.only(top: 10.0),
padding: EdgeInsets.all(5.0),
child: ListTile(
onTap:(){
setState(() {
globalid = friend.friendId;
});
print(friend.friendId);
Navigator.push(context, MaterialPageRoute(builder: (context)=>ChatPage(userid:friend.friendId)));
},
trailing: Container(
// margin: EdgeInsets.only(top:30.0,left:10.0,right:0.0),
child: Text(
friend.totalTexts.toString(),),
leading: Container(
width: 60.0,
height: 60.0,
),
title: Text(friend.username,),
),
);
}
}
Yo need to setState() in getUser() and also check if snapshot has data or not also.so the modified code will be
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import "package:flutter/material.dart";
import 'package:mine_app/textingpage.dart';
class FriendsPage extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _FriendsPage();
}
}
class Friends {
final int theirTexts;
final String username;
final int myTexts;
final int totalTexts;
final String friendId;
Friends(this.theirTexts,this.totalTexts,this.username,this.myTexts,this.friendId);
Friends.fromMap(DocumentSnapshot map)
:assert(map["username"]!=null),
assert(map["myTexts"]!=null),
assert(map["theirTexts"]!=null),
assert(map["totalTexts"]!=null),
assert(map["uid"]!=null),
username = map["username"],
myTexts = map["myTexts"],
theirTexts = map["theirTexts"],
totalTexts = map["totalTexts"],
friendId = map["uid"];
}
class _FriendsPage extends State<FriendsPage> {
String user;
String globalid = "";
Future<void> getuser() async{
setState((){
user = (await FirebaseAuth.instance.currentUser()).uid;
});
}
#override
void initState() {
getuser();
super.initState();
}
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
backgroundColor: Color(0xff723881),
centerTitle: true,
title: Text(
"Chats",
bottom: TabBar(
tabs: [
Tab(icon: Icon(Icons.people), text: "People"),
Tab(icon: Icon(Icons.search), text: "Find"),
],
indicatorColor: Colors.white,
),
),
body: TabBarView(
children: <Widget>[
Container(
child: snapShotBuilder(context)
),
Container()
],
)),
);
}
Widget snapShotBuilder(BuildContext context){
return StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection("users").document(user).collection("friends").snapshots(),
builder:(context,snapshot){
if (snapshot.hasData) {
return myListView(context,snapshot.data.documents);
}else if(snapshot.hasError){
return Center(
child:Text(snapshot.error.toString()));
}else{
return LinearProgressIndicator();
}
} );
}
Widget myListView(BuildContext context,List<DocumentSnapshot> snapshot){
return Container(
child: ListView(
children: snapshot.map((data)=>myfriends(Friends.fromMap(data))).toList(),
),
);
}
Widget myfriends(Friends friend) {
return Container(
margin: EdgeInsets.only(top: 10.0),
padding: EdgeInsets.all(5.0),
child: ListTile(
onTap:(){
setState(() {
globalid = friend.friendId;
});
print(friend.friendId);
Navigator.push(context, MaterialPageRoute(builder: (context)=>ChatPage(userid:friend.friendId)));
},
trailing: Container(
// margin: EdgeInsets.only(top:30.0,left:10.0,right:0.0),
child: Text(
friend.totalTexts.toString(),),
leading: Container(
width: 60.0,
height: 60.0,
),
title: Text(friend.username,),
),
);
}
}
You are right. Widget is built at once after call of initState but you getting user data using Future so it is possilbe that Future is not completed yet. So you just need to wrap your main widget with FutureBuilder:
#override
Widget build(BuildContext context) {
return FutureBuilder<String>(
future: getUser(), // <-- your future
builder: (context,snapshot) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
backgroundColor: Color(0xff723881),
centerTitle: true,
title: Text(
"Chats",
bottom: TabBar(
tabs: [
Tab(icon: Icon(Icons.people), text: "People"),
Tab(icon: Icon(Icons.search), text: "Find"),
],
indicatorColor: Colors.white,
),
),
body: TabBarView(
children: <Widget>[
Container(
child: snapShotBuilder(context)
),
Container()
],
),
),
),
},
);
}

Resources