How to initialize a QuerySnapshot type variable for a 1 document request to FireBase / Firestore with Flutter? - firebase

I'm trying to get documents from a collection with the method FireBaseFirestore.instance.collection("users").where("name", isEqualTo : "something").get() which used to have a return type of QuerySnapshot.
My goal is to make a ListView or anything that can display like a ListView the result(s) of this request.
I have these functions :
This one is to get the documents with the where method
class DataBaseMeth {
getUserByUsername(String username) async{
return fsInstance.collection("users").where("name", isEqualTo: username).get();
}
}
This one is the widget with the result :
class SearchResultTile extends StatelessWidget {
final String username;
const SearchResultTile({
Key? key,
required this.username,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 25.0),
child: Row(
children: [
Column(
children: [
Text(
username,
),//username
],
),
)
],
),
);
}
}
And finally the class of the page :
class SearchPage extends StatefulWidget {...}
class _SearchPageState extends State<SearchPage> {
DataBaseMeth dataBaseMethods = DataBaseMeth();
TextEditingController usernameSearchController = TextEditingController();
QuerySnapshot searchSnapshot; //the only way the code run is to replace the type by dynamic
initSearch(){
dataBaseMethods.getUserByUsername(usernameSearchController.text)
.then((result){
setState((){
searchSnapshot = result;
print("result : $searchSnapshot");
//print("result : ${searchSnapshot.docs[1].data.toString()}");
});
});
}
Widget searchList(){
return searchSnapshot != null ?
ListView.builder(
shrinkWrap: true,
itemCount: searchSnapshot.docs.length,
itemBuilder: (context, index) {
return SearchResultTile(
username: searchSnapshot.docs[index].data.toString(),
personalMessage: "personalMessage");
}
)
:
Container();
}
#override
void initState() {
searchList();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: const MainAppBar(titleText: 'Search truc', mainPage: true),
body: Container(
padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10.0),
child: Column(
children: [
Row(
children: [
Expanded(
child: TextField(
controller: usernameSearchController,
decoration: textFieldInputDecoration("search username..."),
style: whiteText(),
),
),
IconButton(
onPressed: () {
initSearch();
},
icon: const Icon(Icons.search_outlined),
color: const Color(0xFFFFFFFF),
highlightColor: Colors.deepPurple,
splashColor: const Color(0xFF3A206B),
tooltip: "Search",
),
],
),
searchList()
],
),
),
);
}
}
The result of the print of searchSnapshot (when I put it on dynamic) is :
I/flutter (31401): result : Instance of '_JsonQuerySnapshot'
And nothing appears when I tap on the button.

Your fsInstance.collection("users").where("name", isEqualTo: username).get() returns a Future<QuerySnapshot> not a QuerySnapshot, so that's why you can't assign it to QuerySnapshot searchSnapshot. You can assign it to Future<QuerySnapshot> searchSnapshot though.
That also means that if you want to use it in your UI you'll have to either wrap it in a FutureBuilder or pass it to setState().

Related

The argument type ‘Widget’ can’t be assigned to the parameter type ‘String’?

How do I use my custom widget Notes? I unfortunately can't use the full code in the AddNoteScreen.
I got this error when I changed a few things from the class I'm taking. Below I've pasted the instructors code, with my custom widget included. I'll comment below with the other changes I tried that lead me to this error.
Custom widget down to bare bones:
class Notes extends StatelessWidget {
TextEditingController notesController = TextEditingController();
#override
Widget build(BuildContext context) {
return TextField(
controller: notesController,
);
}
}
class AddNoteScreen extends StatefulWidget {
User user;
AddNoteScreen({
required this.user,
});
#override
State<AddNoteScreen> createState() => _AddNoteScreenState();
}
class _AddNoteScreenState extends State<AddNoteScreen> {
TextEditingController titleController = TextEditingController();
TextEditingController notesController = TextEditingController();
bool loading = false;
#override
void initState(){
super.initState(
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor:Color (0xFF162242),
elevation: 0,
),
body: GestureDetector(
onTap: () {
FocusScope.of(context).unfocus();
new TextEditingController().clear();
},
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(20),
child: Column(children: [
Text("Title", style: TextStyle(
color: Colors.white,
),
),
SizedBox(
height: 15,
),
Container(
height: 60,
color: Colors.white,
child: TextField(
style: TextStyle(
color: Color(0xFF192A4F),
),
controller: titleController,
),
),
Notes(), // My Custom Widget
SizedBox(height: 50,),
loading ? Center (child: CircularProgressIndicator(),) : Container(
height: 50,
width: MediaQuery.of(context).size.width,
child: ElevatedButton(
onPressed: ()async{
if (
titleController.text == "" || notesController.text == "") // HERE
{
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("All fields are required")));
} else {
setState(() {
loading = true;
});
await FirestoreService().insertNote(titleController.text, notesController.text, widget.user.uid); // HERE
setState(() {
loading = false;
});
Navigator.pop(context);
}
}, child: Text("Add Note"),
),),
]),),
),
),
);
}
}
^ above I changed notesController.text == "" to Notes == "" and then notesController.text to Notes()
class FirestoreService{
FirebaseFirestore firestore = FirebaseFirestore.instance;
Future insertNote(String title, String notes, String userId)async{
try{
await firestore.collection('notes').add({
"title":title,
"notes":notes,
"userId": userId
});
} catch (e) {}
}
}
^ above I changed String to Widget for notes
class NoteModel {
String id;
String title;
String notes;
String userId;
NoteModel({
required this.id,
required this.title,
required this.notes,
required this.userId
});
factory NoteModel.fromJson(DocumentSnapshot snapshot){
return NoteModel(
id: snapshot.id,
title: snapshot['title'],
notes: snapshot['notes'],
userId: snapshot['userId']
);
}
}
^ above I changed String to Widget for notes
class HomeScreen extends StatefulWidget {
#override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
final user = FirebaseAuth.instance.currentUser!;
FirebaseFirestore firestore = FirebaseFirestore.instance;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Notes'),
centerTitle: true,
backgroundColor: Color (0xFF162242),
actions: [
TextButton(onPressed: () => FirebaseAuth.instance.signOut(), child: Text("Sign Out", style: TextStyle(color: Colors.white),),),
],
),
body: StreamBuilder(
stream: FirebaseFirestore.instance.collection("notes").where('userId', isEqualTo: user.uid).snapshots(),
builder: (context, AsyncSnapshot snapshot){
if (snapshot.hasData){
if(snapshot.data.docs.length > 0){
return ListView.builder(
itemCount: snapshot.data.docs.length,
itemBuilder: (context,index) {
NoteModel note = NoteModel.fromJson(snapshot.data.docs[index]);
return Card(
margin: EdgeInsets.only(top: 16, left: 10, right: 10, bottom: 16),
child: Column(
children: [
ListTile(
title: Center(child: Text(note.title, style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
),
),
onTap: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) => EditNoteScreen(),));},
),
ListTile(title: Center(child:
Container(
height: 300,
child:
Text(note.notes),),), // HERE
),
]),
);
}
);
}else Center(child: Text("No notes available", style: TextStyle(color: Colors.white),),);
}
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
],
),
);
}),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) => AddNoteScreen(user: user)));
},
backgroundColor: Color (0xFF162242),
child: Icon(Icons.add),
),
);
}
}
^ Text(note.notes) is where I get the error.
I don't really know what I'm doing but can something like this work ? Totally different answer is okay too!
I'm sorry that's a lot of code. Any help is appreciated.
Also link to the class if anyone is interested https://skl.sh/3wxeMVF
Assumptions
Based on the code and comments I guess the actual class NoteModel and Notes are looking something like this:
class NoteModel {
Notes notes;
...
}
class Notes extends StatelessWidget {
TextEditingController notesController = TextEditingController();
...
}
Problem
This explains the error message The argument type ‘Widget’ can’t be assigned to the parameter type ‘String’?:
Text(note.notes) expects note.notes to be a String. Whereas you changed note.notes to be the Widget Notes.
Solution 1
The widget Text() expects Strings, not another Widget. Thus,
change notes back to a String:
class NoteModel {
String notes;
...
}
Build the rest of your code around this NoteModel, do not change it.
Solution 2
If you want to use
class NoteModel {
Notes notes;
...
}
then the Text widget would be called something like this:
Text(note.notes.notesController.text)
However, this is NOT recommended, as a NoteModel is a data model. And data models should never hold Widgets. A Widget is meant for showing data, not for holding it. A data model and a Widget serve different functions. Keep them separated.
Firebase
Note, that one cannot store whole Widgets (like Notes) in in Firebase but only Strings, Numbers etc.
(Please always post your current code, not code that is indirectly related related to the issue. Otherwise, people will find it very difficult to spot the problem.)

How do I write to firebase using a TextFormField in a ListView in flutter

Hi Im trying to use List views to make the UI more interactive and appealing, however I cant figure out a way to pass the TextEditingController() pass through to other pages. I've attached the relevant pages of code below.
admin_exercise.dart
this creates both list views this is then passed to admin_screen.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
final _firestore = Firestore.instance;
late FirebaseUser users;
class ExerciseView extends StatefulWidget {
const ExerciseView({Key? key}) : super(key: key);
#override
State<ExerciseView> createState() => _ExerciseViewState();
}
class _ExerciseViewState extends State<ExerciseView> {
void getUsers() {
users.email.toString();
}
var selectedUser;
bool setDefaultUser = true;
var selectedExercise;
bool setDefaultExercise = true;
int set1 = 0;
List<Widget> _cardList = [];
void _addCardWidget() {
setState(() {
_cardList.add(SetCard(
setNo: (set1 + 1),
exercise: selectedExercise,
));
});
}
void _deleteCardWidget() {
setState(() {
_cardList.removeLast();
});
}
#override
Widget build(BuildContext context) {
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Center(
child: StreamBuilder<QuerySnapshot>(
stream: _firestore
.collection('exercises')
.orderBy('Title')
.snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) return Container();
if (setDefaultExercise) {
selectedExercise = snapshot.data?.documents[0]['Title'];
}
return DropdownButton(
isExpanded: false,
value: selectedExercise,
items: snapshot.data?.documents.map((value2) {
return DropdownMenuItem(
value: value2['Title'],
child: Text('${value2['Title']}'),
);
}).toList(),
onChanged: (value2) {
setState(
() {
// Selected value will be stored
selectedExercise = value2;
// Default dropdown value won't be displayed anymore
setDefaultExercise = false;
},
);
},
);
},
),
),
ElevatedButton(
onPressed: () {
setState(() {
_addCardWidget();
set1++;
});
},
child: Icon(Icons.add)),
Text('Sets: $set1'),
ElevatedButton(
onPressed: () {
_deleteCardWidget();
setState(() {
set1--;
});
},
child: Icon(Icons.remove))
],
),
ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: _cardList.length,
itemBuilder: (context, index) {
return _cardList[index];
}),
],
);
}
}
class SetCard extends StatelessWidget {
SetCard({required this.setNo, required this.exercise});
late int setNo;
late String exercise;
final repTextController = TextEditingController();
final notesTextController = TextEditingController();
Future<void> insertData(final reps) async {
_firestore.collection("plans").add(reps).then((DocumentReference document) {
print(document.documentID);
}).catchError((e) {
print(e);
});
}
#override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
// added in exercise here to help to understand how to write to firebase
Text('Set $setNo, $exercise'),
Row(
children: [
Expanded(
flex: 1,
child: TextFormField(
controller: repTextController,
decoration: InputDecoration(hintText: 'Reps...'),
keyboardType: TextInputType.number,
),
),
SizedBox(
width: 10,
),
Expanded(
flex: 4,
child: TextFormField(
controller: notesTextController,
decoration: InputDecoration(hintText: 'Notes...'),
keyboardType: TextInputType.number,
),
),
],
),
],
);
}
}
admin_screen.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:intl/intl.dart';
import 'package:fitness_guide/components/admin_exercise.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class AdminScreen extends StatefulWidget {
static const String id = 'AdminScreen';
const AdminScreen({Key? key}) : super(key: key);
#override
State<AdminScreen> createState() => _AdminScreenState();
}
class _AdminScreenState extends State<AdminScreen> {
TextEditingController dateinput = TextEditingController();
final _auth = FirebaseAuth.instance;
final _firestore = Firestore.instance;
late FirebaseUser users;
void getUsers() {
users.email.toString();
}
var selectedUser;
bool setDefaultUser = true;
var selectedExercise;
bool setDefaultExercise = true;
int set1 = 0;
#override
void initState() {
dateinput.text = ""; //set the initial value of text field
super.initState();
}
List<Widget> _exerciseList = [];
void _addExerciseWidget() {
setState(() {
_exerciseList.add(ExerciseView());
});
}
void _deleteExerciseWidget() {
setState(() {
_exerciseList.removeLast();
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton.extended(
onPressed: () {
//submit to fbase here
},
label: const Text('Submit'),
icon: const Icon(Icons.thumb_up),
backgroundColor: Color(0xff75D6F2),
),
body: ListView(
physics: BouncingScrollPhysics(),
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
SizedBox(
height: 20,
),
Container(
padding: EdgeInsets.symmetric(horizontal: 15),
height: 50,
child: Center(
child: TextField(
controller:
dateinput, //editing controller of this TextField
decoration: InputDecoration(
icon: Icon(Icons.calendar_today), //icon of text field
labelText: "Enter Date" //label text of field
),
readOnly:
true, //set it true, so that user will not able to edit text
onTap: () async {
DateTime? pickedDate = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(
2000), //DateTime.now() - not to allow to choose before today.
lastDate: DateTime(2101));
if (pickedDate != null) {
print(
pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000
String formattedDate =
DateFormat('yyyy-MM-dd').format(pickedDate);
print(
formattedDate); //formatted date output using intl package => 2021-03-16
//you can implement different kind of Date Format here according to your requirement
setState(() {
dateinput.text =
formattedDate; //set output date to TextField value.
});
} else {
print("Date is not selected");
}
},
))),
Center(
child: StreamBuilder<QuerySnapshot>(
stream: _firestore
.collection('users')
.orderBy('email')
.snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
// Safety check to ensure that snapshot contains data
// without this safety check, StreamBuilder dirty state warnings will be thrown
if (!snapshot.hasData) return Container();
// Set this value for default,
// setDefault will change if an item was selected
// First item from the List will be displayed
if (setDefaultUser) {
selectedUser = snapshot.data?.documents[0]['email'];
}
return DropdownButton(
isExpanded: false,
value: selectedUser,
items: snapshot.data?.documents.map((value1) {
return DropdownMenuItem(
value: value1['email'],
child: Text('${value1['email']}'),
);
}).toList(),
onChanged: (value1) {
setState(
() {
// Selected value will be stored
selectedUser = value1;
// Default dropdown value won't be displayed anymore
setDefaultUser = false;
},
);
},
);
},
),
),
//Row below for the first exercise sets etc
ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: _exerciseList.length,
itemBuilder: (context, index) {
return _exerciseList[index];
}),
Center(
child: Text('Add another Exercise...'),
),
ElevatedButton(
onPressed: () {
_addExerciseWidget();
},
child: Icon(Icons.add),
),
],
),
],
),
);
}
}```
p.s. sorry for any spagetti code
[Image shows the layout UI I'm trying to achieve][1]
[1]: https://i.stack.imgur.com/d3qxg.png

ListView.builder only loads after hot-reloading flutter app

When a user logs into my flutter app, they have to log in, then they are brought to a screen with a feed of posts. I use a ListView.builder to take a list of posts from my database and create the feed of posts. My issue is that when the feed screen is initially launched, the ListView doesn't load. As soon as I hot-reload the app the list does load. I imagine there's a very obvious minor mistake in my code but I just can't find it. I will put all of the code from the feed screen below, please take a look and let me know if you see the mistake.
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
static const String id = "home_screen";
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
// List allposts = [(post: Post, owner: String)];
Color _likeButtonColor = Colors.black;
Widget _buildPost(String username, String imageUrl, String caption) {
return Container(
color: Colors.white,
child: Column(
children: [
Container(
height: 50,
color: Colors.deepOrangeAccent[100],
child: Row(
children: [
SizedBox(width: 5),
CircleAvatar(),
SizedBox(width: 5),
Text(username, style: TextStyle(fontSize: 15)),
SizedBox(width: 225),
Icon(Icons.more_horiz)
],
),
),
Stack(
children: [
Image.asset("images/post_background.jpg"),
Padding(
padding: const EdgeInsets.all(20.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: Image.network(imageUrl, fit: BoxFit.cover)),
),
],
),
Container(
height: 100,
child: Column(
children: [
const SizedBox(height: 5),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
IconButton(
onPressed: () {
setState(() {
HapticFeedback.lightImpact();
});
},
icon: Icon(Icons.thumb_up_alt_outlined, size: 30)),
Text("l", style: TextStyle(fontSize: 30)),
Icon(Icons.ios_share, size: 30)
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(caption, style: const TextStyle(fontSize: 15))
],
)
],
),
)
],
),
);
}
List<Post> listPosts = [];
fetchPosts() async {
final userRef = FirebaseFirestore.instance.collection('users');
final QuerySnapshot result = await userRef.get();
result.docs.forEach((res) async {
print(res.id);
QuerySnapshot posts = await userRef.doc(res.id).collection("posts").get();
posts.docs.forEach((res) {
listPosts.add(Post.fromJson(res.data() as Map<String, dynamic>));
});
});
}
#override
void initState() {
fetchPosts();
print(listPosts);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: listPosts.length,
itemBuilder: (BuildContext context, int index) {
// We retrieve the post at index « index »
final post = listPosts[index];
// Replace with your actual implementation of _buildPost
return _buildPost(post.id, post.postUrlString, post.caption);
}),
);
}
}
The reason is that you need to rebuild your screen to show the reflected changes after performing an async operation (use setState to rebuild the UI). And secondly .forEach loop is not built to carry async stuff and are less efficient then a normal for loop so its better to change it.
fetchPosts() async {
final userRef = FirebaseFirestore.instance.collection('users');
final QuerySnapshot result = await userRef.get();
for(var res in result.docs)async{
print(res.id);
QuerySnapshot posts = await userRef.doc(res.id).collection("posts").get();
posts.docs.forEach((res) {
listPosts.add(Post.fromJson(res.data() as Map<String, dynamic>));
});
}
setState((){});//call it after end of your function
}
Ps:- You can use a variable named loading to show progress indicator and set it to false after fetching data in setState.

The argument type 'UserResult' can't be assigned to the parameter type 'UserSearch'

I am trying to make a search functionality that will help a user search for another user. I have created a stateful widget UserSearch and a stateless Widget UserResult. UserSearch builds the results based on UserResult's data. However I am unable to pass UserResult as an argument in UserSearch and I have no clue why. Any help will be great. Thanks in advance
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:vibing_app/feed.dart';
import 'package:vibing_app/model/user.dart';
class UserSearch extends StatefulWidget {
#override
_UserSearchState createState() => _UserSearchState();
}
class _UserSearchState extends State<UserSearch> {
final userRef = FirebaseFirestore.instance.collection('user');
TextEditingController searchController = new TextEditingController();
Future<QuerySnapshot> searchResults;
handleSearch(String query)
{
Future<QuerySnapshot> users = userRef.where("first_name"+ "last_name", isGreaterThanOrEqualTo: query).get();
setState(() {
searchResults = users;
});
}
clearSearch()
{
searchController.clear();
}
AppBar buildSearchField()
{
return AppBar(
backgroundColor: Colors.yellow,
title: TextFormField(
controller: searchController,
decoration: InputDecoration(
hintText: "Search for a user",
filled: true,
suffixIcon: IconButton(
icon: Icon(Icons.clear),
onPressed: clearSearch,
),
),
onFieldSubmitted: handleSearch,
),
);
}
Container searchContainer(){
final Orientation orientation = MediaQuery.of(context).orientation;
return Container(
child: Center(
child: ListView(
shrinkWrap: true,
children: [
Text("Find users...",
textAlign: TextAlign.center,
),
],
),
),
);
}
buildSearchResults()
{
return FutureBuilder(
future: searchResults,
builder: (context, snapshot){
if(!snapshot.hasData)
return CircularProgressIndicator();
List<UserSearch> searchResults = [];
snapshot.data.forEach((docu){
AppUser user = AppUser.fromDocument(docu);
UserResult searchResult = UserResult(user);
searchResults.add(UserResult(user)); //This part is giving me the error
});
return ListView(
children: searchResults,
);
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: buildSearchField(),
body:
searchResults == null ? searchContainer(): buildSearchResults(),
);
}
}
class UserResult extends StatelessWidget {
final AppUser user;
UserResult(this.user);
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: [
GestureDetector(
onTap: showUserProfile(context,profileID: user.userId),
child: ListTile(
leading: CircleAvatar(
backgroundColor: Colors.yellow,
backgroundImage: Image.network(user.photoURL).image,
),
title: Text(user.firstName + " " + user.lastName),
),
),
Divider(
height: 2.0,
color: Colors.white54,
),
],
),
);
}
}
It is a different types. You need to change List type to UserList:
List<UserResult> searchResults = [];

Firestore value returns only one value

whenever I try to retrieve data from firestore,only one part is called
You can see that I have a ListTile with a title and a Subtitle
Now only the data in the subtitle is being displayed and it requires no null indication
But the title requires the null indication but still it does not returns the string This is my firestore
Thank You
// ...
class SearchPage extends StatefulWidget {
#override
_SearchPageState createState() => _SearchPageState();
}
class _SearchPageState extends State<SearchPage> {
TextEditingController searchController = TextEditingController();
Future<QuerySnapshot> searchResultsFuture;
handleSearch(String query){
Future<QuerySnapshot> users = usersReference.where("profilename",isGreaterThanOrEqualTo: query ).getDocuments();
setState(() {
searchResultsFuture = users;
});
//searchResultsFuture = users;
}
clearSearch(){
searchController.clear();
}
AppBar buildSearchField(){
return AppBar(
backgroundColor: Colors.white,
title: TextFormField(
controller: searchController,
decoration: InputDecoration(
hintText: "Search Your Friends",
filled: true,
prefixIcon: Icon(
Icons.account_box,
size: 28.0,
),
suffixIcon: IconButton(
icon: Icon(Icons.clear),
onPressed: clearSearch,
),
),
onFieldSubmitted: handleSearch,
),
);
}
Container buildNoContent(){
final Orientation orientation = MediaQuery.of(context).orientation;
return Container(
child: ListView(
shrinkWrap: true,
children: <Widget>[
Icon(Icons.group, color: Colors.white,size: orientation == Orientation.portrait ? 400.0 : 200.0 ,),
Text("Find Users",textAlign: TextAlign.center,style: TextStyle(color: Colors.white,fontStyle: FontStyle.italic,fontWeight: FontWeight.w600,fontSize: 65.0),),
],
),
);
}
buildSearchResults() {
return FutureBuilder(
future: searchResultsFuture,
builder: (context, snapshot){
if(!snapshot.hasData){
return circularProgress();
}
List<UserResult> searchResults = [];
snapshot.data.documents.forEach((doc){
User user = User.fromDocument(doc);
UserResult searchResult = UserResult(user);
searchResults.add(searchResult);
});
return ListView(
children: searchResults,
);
}
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).primaryColor.withOpacity(0.8) ,
appBar: buildSearchField(),
body: searchResultsFuture == null ? buildNoContent() : buildSearchResults(),
);
}
}
class UserResult extends StatelessWidget {
final User eachUser;
UserResult(this.eachUser);
#override
Widget build(BuildContext context) {
return Container(
color: Theme.of(context).primaryColor.withOpacity(0.7),
child: Column(children: <Widget>[
GestureDetector(
onTap: ()=> print("tapped"),
child: ListTile(
leading: CircleAvatar(
backgroundColor: Colors.grey,
backgroundImage: CachedNetworkImageProvider(eachUser.url),
),
title: eachUser.profileName != null ? Text(eachUser.profileName,
style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold),): 'User',
subtitle: Text(eachUser.username,style: TextStyle(color: Colors.white),),
),
),
Divider(
height: 2.0,
color: Colors.white54,
),
],),
);
}
}
try uploading a more detailed code so as to get insights of what might be wrong.
I thinnk you shoud try to call setSate in
void didChangeDependencies() {
super.didChangeDependencies();
WidgetsBinding.instance.addPostFrameCallback((callback) async {
/// logic here!
eachUser = get data from firebase;
after that call setState();
});
}
I think the proplem is:
Future<QuerySnapshot> users = usersReference.where("profilename",isGreaterThanOrEqualTo: query ).getDocuments();
setState(() {
searchResultsFuture = users;
});
searchResultsFuture get value when users hadn't completed

Resources