Flutter perfect message when snapshot.data doesn't have data in Future - flutter

in this below code i try to show list is empty message when snapshot.hasData is false
body: FutureBuilder(
future: Provider.of<TicketRepliesTableDao>(context).find(ticketId: _ticket.id),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasData) {
final List<TicketRepliesTableData> ticketReplies = snapshot.data;
if (ticketReplies.isNotEmpty) {
}
} else {
return _loader(message: 'list is empty');
}
} else
return CircularProgressIndicator();
},
),
but in that i have CircularProgressIndicator() always, in view,even it doesn't have any data and ticketReplies is empty

Update your builder, with this logic.
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasData) {
// show your data
return Text(snapshot.data);
} else {
// show list is empty
return Text("List is empty");
}
}
// by default show loading bar
return CircularProgressIndicator();
}

Related

returning a FutureBuilder as the result of a FutureBuilder Flutter

I'm creating an add friend page in Flutter/Firebase. I used a StreamBuilder to see the changes of the username input. Then I used a FutureBuilder as the result of the StreamBuilder to get my List of User. To verify that the users aren't already in thisUser's friend list, I'm using an other FutureBuilder as the result of the first one. And I still do the same for the friend requests.
It works but I'm pretty sure that not the right way. Could someone explain me how to do that more properly?
StreamBuilder(
stream: controller.usernameStream.stream,
builder: (context, snapshot) {
if (snapshot.hasData) {
String usernameSearched = snapshot.data!;
return FutureBuilder(
future: _userRepo.getUsersStartsByUsername(usernameSearched),
builder: (context, snapshotUsers){
if(snapshotUsers.connectionState == ConnectionState.done){
if (snapshotUsers.hasData){
return controller.futureBuilderFriends(thisFireUser, snapshotUsers);
} else {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Center(child: Text(AppLocalizations.of(context)!.noUsers)),
);
}
}
return Container();
},
);
}
return Container();
},
)
FutureBuilder<List<String>> futureBuilderFriends(User? thisFireUser, AsyncSnapshot<List<U.User>> snapshotUsers) {
return FutureBuilder(
future: _userRepo.getFriendsId(thisFireUser!.uid),
builder: (BuildContext context, AsyncSnapshot<List<String>> snapshotFriends) {
if (snapshotFriends.connectionState == ConnectionState.done) {
if(snapshotFriends.hasData){
return futureBuilderMyFriendRequests(thisFireUser, snapshotFriends.data!, snapshotUsers);
} else {
return futureBuilderMyFriendRequests(thisFireUser, [], snapshotUsers);
}
} else {
return Container();
}
},
);
}
FutureBuilder<List<String>> futureBuilderMyFriendRequests(User thisFireUser, List<String> friends, AsyncSnapshot<List<U.User>> snapshotUsers) {
return FutureBuilder(
future: _userRepo.getFriendRequestsId(thisFireUser.uid),
builder: (BuildContext context, AsyncSnapshot<List<String>> snapshotFriendRequests) {
if (snapshotFriendRequests.connectionState == ConnectionState.done) {
if(snapshotFriendRequests.hasData){
return buildAddFriends(context, snapshotUsers.data!, thisFireUser, friends, snapshotFriendRequests.data!);
} else {
return buildAddFriends(context, snapshotUsers.data!, thisFireUser, friends, []);
}
} else {
return Container();
}
},
);
}
Looks like you are on vanilla architecture. Please make use of bloc or Riverpod and use the transfrom functions and emit the states accordingly

The body might complete normally, causing 'null' to be returned

body: FutureBuilder(
future: determinePosition(),
builder: (context, snapshot) //error here{
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
} else if (snapshot.hasError) {
return Text("Error ");
}else if(snapshot.hasData){
return Column(
children: [
Text(currentAddress),
The body might complete normally, causing 'null' to be returned, but the return type, 'Widget', is a potentially non-nullable type. why it is wrong ? help me
The problem is that you're using else if instead of else. By using else if, you're telling Dart to follow this set of conditions, but what if there's another condition? that won't be handled, and will return null.
To fix the issue, use else instead of else if in the last clause:
FutureBuilder(
future: determinePosition(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
} else if (snapshot.hasError) {
return Text("Error ");
} else {
return Column(
children: [
Text('test'),
],
);
}
})
The potential solution is remove last else if (which is snapshot.hasData) and directly return the the column same as below
body: FutureBuilder(
future: determinePosition(),
builder: (context, snapshot) //error here{
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
} else if (snapshot.hasError) {
return Text("Error ");
}
return Column(
children: [
Text(currentAddress),

How to observe Firebase changes in Flutter using StreamBuilder

I am trying to observe Firebase collection changes. In the first run, Listview is not building. After changing data on Firebase, then listview is rendered properly but previous snapshot is used because I see my old data on the screen.
Any idea to find the error?
#override
Widget build(BuildContext context) {
return BlocListener<VoteCubit, VoteState>(
listener: (context, state) {
if (state.status == FormStatus.success) {
print("Success");
} else if (state.status == FormStatus.inprogress) {
print("In progress");
} else if (state.status == FormStatus.fail) {
print("fail");
} else {
print("Empty Area");
}
},
child: StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance.collection('liveSurvey').snapshots(),
builder: (context, snapshot) {
final voteCubit = context.read<VoteCubit>();
final voteState = voteCubit.state;
if (snapshot.hasData) {
voteCubit.getAllRooms(snapshot);
print("Here");
return ListView.builder(
itemCount: voteState.rooms.length,
itemBuilder: (context, i) {
print("Inside Listview");
. . .
Use stream builder like this for real time data.
child: StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection("travellers/India/details")
.where(
'firestore_id',
isEqualTo: widget.get_firestore_id,
)
.snapshots(),
builder:
(BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
print('play lodader')
}else if (snapshot.hasData) {
print('your_ui_here')
}

How we need work with snapshot and futurebuilder?

For the moment when i use futurebuilder and snapshot, i do like that :
So in future i set the function with the data. After i test snapshot.connectionState with waiting. What do you think about this way of working, i am not sure it is correct
FutureBuilder(
future: ListLotto,
builder: (BuildContext context, AsyncSnapshot snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return new Center(
child: new CircularProgressIndicator(),);
default:
if (snapshot.hasError) {
return new Center(
child: new Text('Error: ${snapshot.error}'),);
}
else {
List<Lotto_grid> values = snapshot.data;
if (values.isEmpty) {
return Container(
FutureBuilder(
future: myFuture,
initialData: initialValue,//specify it if necessary
builder: (BuildContext context, AsyncSnapshot snapshot) {
switch(snapshot.connectionState){
case ConnectionState.done:
if(snapshot.hasError) {
return myErrorWidget();
} else if(snapshot.hasData) {
return MyDataWidget();
} else{//if snapshot.data == null
return MyOtherWidget();
}
default:
return CircularProgressIndicator();
}
}
)
This one is better as it checks if data is null so you don't get NullPointerException at this line:
List values = snapshot.data;

How to get the result of a future within the builder method of a FutureBuilder widget?

I have looked all over and cannot seem to find a solution to this problem. I have a Future<bool> = isAuth.
I have a future builder defined as follows:
FutureBuilder(
future: isAuth,
builder(context, snapshot){
if(connectionState == connectionState.done){
// Some Code Here
}
if(connectionState == ConnectionState.waiting){
CircularProgressIndicator()
}
}
My question is, how do I return one widget if isAuth returns true, and another if isAuth returns false? I am displaying a loading spinner while waiting on the result of isAuth, and once I have the result, I want to display one of two forms?
You can access a FutureBuilder's future value with snapshot.data.
Don't forget to check if snapshot.data is defined using snapshot.hasData :
FutureBuilder<bool>(
future: isAuth,
builder: (context, snapshot) {
if(connectionState == connectionState.done){
if (snapshot.hasData){
if (snapshot.data) return TrueWidget();
else return FalseWidget();
// Or with a one-liner :
// return snapshot.data ? TrueWidget() : FalseWidget();
}
}
if(connectionState == ConnectionState.waiting){
return CircularProgressIndicator(); // Don't forget to return a widget in a builder method
}
}
)
new FutureBuilder<bool>(
future: isAuth, // async work getting the call for true of false
builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
bool value = snapshot.data;
switch (snapshot.connectionState) {
case ConnectionState.waiting: return new Text('Loading....');
default:
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
else
return value ?
new Text('sample one'): Text('sample two')
}
},
)