showing all users images in listview with firebase - firebase

In my app, any user can add an Ad and, in home screen, with all Ads showing up in a list view, I get info of every single Ad from the table of cars in firebase; but I want to show the profile images of this user by sending the user id and getting the image from users table.
My function to get data from firebase:
Future<DocumentSnapshot> getAdData(String uid)async{
return await FirebaseFirestore.instance.collection('users').doc(uid).
get();
}
My homescreen:
import 'package:cargaaaalery/functions.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'globalVar.dart';
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
FirebaseAuth auth = FirebaseAuth.instance;
String? username;
String? userNumber;
String? carPrice;
String? carModel;
String? description;
String? urlImage;
String? carLocation;
String? carColor;
QuerySnapshot? cars;
// DocumentSnapshot? users;
String? usersImg;
CarMethods carobj = new CarMethods();
dynamic carUserId;
Future<bool?> showDialogForAddingData() async {
return showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: Text(
"post a new AD",
style: TextStyle(
fontSize: 22, fontFamily: "Bebas", letterSpacing: 2),
),
content: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
decoration: InputDecoration(hintText: "Enter your number"),
onChanged: (val) {
userNumber = val;
},
),
SizedBox(
height: 5,
),
TextField(
decoration:
InputDecoration(hintText: "Enter your car price"),
onChanged: (val) {
carPrice = val;
},
),
SizedBox(
height: 5,
),
TextField(
decoration:
InputDecoration(hintText: "Enter your car name"),
onChanged: (val) {
carModel = val;
},
),
SizedBox(
height: 5,
),
TextField(
decoration:
InputDecoration(hintText: "Enter your car Color"),
onChanged: (val) {
carColor = val;
},
),
SizedBox(
height: 5,
),
TextField(
decoration:
InputDecoration(hintText: "Enter your car description"),
onChanged: (val) {
description = val;
},
),
SizedBox(
height: 5,
),
TextField(
decoration:
InputDecoration(hintText: "Enter your car Image"),
onChanged: (val) {
urlImage = val;
},
),
SizedBox(
height: 5,
),
TextField(
decoration:
InputDecoration(hintText: "Enter your car Location"),
onChanged: (val) {
carLocation = val;
},
),
SizedBox(
height: 5,
),
],
),
),
actions: [
ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text("Cancel"),
),
ElevatedButton(
onPressed: () {
Map<String, dynamic> carData = {
'username': getUsername,
'uId': userId,
'userNumber': this.userNumber,
'carPrice': this.carPrice,
'carModel': this.carModel,
'carLocation': this.carLocation,
'carColor': this.carColor,
'description': this.description,
'urlImage': this.urlImage,
'imgPro': userImageUrl,
'time': DateTime.now(),
};
carobj.addData(carData).then((value) {
print("data add successfuly");
Navigator.push(context,
MaterialPageRoute(builder: (context) {
return HomeScreen();
}));
}).catchError((onError) {
print(onError);
});
},
child: Text("Add Now"),
),
],
);
});
}
getimage()async{
await carobj.getAdData(carUserId).then((res){
setState(() {
usersImg=(res.data() as Map)['imgPro'].toString();
});
});
}
getMyData() async {
await FirebaseFirestore.instance
.collection('users')
.doc(userId)
.get()
.then((result) {
setState(() {
userImageUrl = result.data()!['imgPro'];
getUsername = result.data()!['username'];
});
});
}
#override
void initState() {
super.initState();
userId = FirebaseAuth.instance.currentUser!.uid;
userEmail = FirebaseAuth.instance.currentUser!.email!;
print("userid is $userId and email is $userEmail");
carobj.getData().then((results) {
setState(() {
cars = results;
});
});
getMyData();
}
#override
Widget build(BuildContext context) {
Widget? showCarsList() {
if (cars != null) {
return ListView.builder(
itemCount: cars!.docs.length,
padding: EdgeInsets.all(8),
itemBuilder: (context,index) {
carUserId= (cars!.docs[index].data() as Map)['uId'];
getimage();
return Card(
child: Column(
children: [
ListTile(
leading:GestureDetector(
onTap: (){},
child: Container(
width: 60,
height:60,
decoration: BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
image: NetworkImage(
((usersImg!)),scale: 0.9),
fit:BoxFit.fill
)
),
),
) ,
title: GestureDetector(
onTap: (){
},
child: Text((cars!.docs[index].data() as Map)['username'].toString()),
),
subtitle: GestureDetector(
onTap: (){},
child:
Row(
children: [
((cars!.docs[index].data() as Map)['carLocation'] != null)
? Text((cars!.docs[index].data() as Map)['carLocation'] ,
style:TextStyle(color: Colors.black.withOpacity(0.6))
):Text("unknown" ,
style:TextStyle(color: Colors.black.withOpacity(0.6))
),
SizedBox(width: 4.0,),
Icon(Icons.location_pin,color: Colors.grey,)
],
),
),
trailing:
(cars!.docs[index].data() as Map)['uId']==userId?
Row(
mainAxisSize: MainAxisSize.min,
children: [
GestureDetector(
onTap: (){
},
child: Icon(Icons.edit),
),
SizedBox(width: 20,),
GestureDetector(
onDoubleTap: (){
},
child: Icon(Icons.delete_forever),
),
],
):
Row( mainAxisSize: MainAxisSize.min,
children: [],
)
,
)
],
),
);
},
);
}
}
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.refresh, color: Colors.white),
onPressed: () {},
),
actions: [
TextButton(
onPressed: () {},
child: Padding(
padding: EdgeInsets.all(10),
child: Icon(
Icons.person,
color: Colors.white,
),
)),
TextButton(
onPressed: () {},
child: Padding(
padding: EdgeInsets.all(10),
child: Icon(
Icons.search,
color: Colors.white,
),
)),
TextButton(
onPressed: () {},
child: Padding(
padding: EdgeInsets.all(10),
child: Icon(
Icons.login_outlined,
color: Colors.white,
),
))
],
flexibleSpace: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.blueAccent, Colors.redAccent])),
),
title: Text("home page"),
),
body: Center(
child: showCarsList(),
),
floatingActionButton: FloatingActionButton(
tooltip: 'add post',
child: Icon(Icons.add),
onPressed: () {
showDialogForAddingData();
},
),
);
}
}
Where I get image (from home screen code):
getimage()async{
await carobj.getAdData(carUserId).then((res){
setState(() {
usersImg=(res.data() as Map)['imgPro'].toString();
});
});
}
Where I set image to listview (from home screen code):
#override
Widget build(BuildContext context) {
Widget? showCarsList() {
if (cars != null) {
return ListView.builder(
itemCount: cars!.docs.length,
padding: EdgeInsets.all(8),
itemBuilder: (context,index) {
carUserId= (cars!.docs[index].data() as Map)['uId'];
getimage();
return Card(
child: Column(
children: [
ListTile(
leading:GestureDetector(
onTap: (){},
child: Container(
width: 60,
height:60,
decoration: BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
image: NetworkImage(
((usersImg!)),scale: 0.9),
fit:BoxFit.fill
)
),
),
) ,
Output of the code:

You're getting the behaviour because you are calling setState in the build method. This causes the build method to get called again and it makes the network request and calls the build method again...
You can fix this by using a FutureBuilder to get the data. Follow these steps:
Update the getimage method to return the image url instead of changing the state:
Future<String> getimage() async {
var res = await carobj.getAdData(carUserId);
return (res.data() as Map)['imgPro'].toString();
}
Declare a variable _imageFuture to hold the result of the getimage network request:
Future<String> _imageFuture;
Assign the getimage method to _imageFuture in the initState:
#override
void initState() {
...
_imageFuture = getimage();
}
Update the ListTile to use a FutureBuilder which gets the image from the _imageFuture Future:
ListTile(
leading:GestureDetector(
onTap: (){},
child: FutureBuilder<String>(
future: _imageFuture,
builder: (context, AsyncSnapshot<String> snapshot) {
if (snapshot.data == null) {
return Center(child: CircularProgressIndicator());
} else {
String usersImg = snapshot.data;
return Container(
width: 60,
height:60,
decoration: BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
image: NetworkImage(
((usersImg!)),scale: 0.9),
fit:BoxFit.fill
)
),
),
);
}
}
),
),
)

Related

Flutter: Firebase Storage is not uploading multiple images, it always repeat the same path?

class CategoryScreen extends StatefulWidget {
static const routeName = '/category-screen';
#override
_CategoryScreenState createState() => _CategoryScreenState();
}
class _CategoryScreenState extends State<CategoryScreen> {
#override
Widget build(BuildContext context) {
//from co_detai_screen.dart
final companyId = ModalRoute.of(context).settings.arguments as String;
//
final _form = GlobalKey<FormState>();
String _car = '';
String _carModel = '';
File carImage;
String ranDom = randomBetween(0, 300).toString();
void _submitCarCategory() async{
final isValid = _form.currentState.validate();
if(isValid){
_form.currentState.save();
//.... upload image here
/*===============================Here is firebase storage work==============================*/
final ref = FirebaseStorage.instance.ref().child('cars').child(ranDom + '.jpg');
await ref.putFile(carImage);
//kan fe .onComplete ba3ed (image)**strong text**
//.... upload image here
//... now want to get this image into the firestore
final url = await ref.getDownloadURL();
//... now want to get this image into the firestore
FirebaseFirestore.instance.collection('companies').doc(companyId).collection('category').doc().set(({
'carName': _car,
'carModel': _carModel,
'car_image': url
}));
Navigator.of(context).pop();
}
}
void _pickedImage(File image){
carImage = image;
}
void _showDialog(){
showDialog(context: context, builder: (context)=> AlertDialog(
title: Text('Add Category'),
content: SingleChildScrollView(
child: Form(
key: _form,
child: Container(
height: 450,
width: double.infinity,
padding: EdgeInsets.all(20),
child: Column(
children: [
Text('Add Category', style: TextStyle(fontSize: 16),),
SizedBox(height: 10,),
UserImagePicker(_pickedImage),
TextFormField(decoration: InputDecoration(labelText: 'Car'),
onSaved: (value){
_car = value;
},
),
TextFormField(
decoration: InputDecoration(labelText: 'Car model'),
onSaved: (value){
_carModel = value;
},
),
SizedBox(height: 20,),
FlatButton(
onPressed: (){
_submitCarCategory();
},
child: Text('Add'),
color: Colors.indigo,
textColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)
),
),
],
),
),
),
),
),
);
}
return FutureBuilder(
future: FirebaseFirestore.instance.collection('companies').doc(companyId).get(),
builder: (ctx, futureSnapshot){
if(futureSnapshot.hasData){
return Scaffold(
appBar: AppBar(title: Row(
children: [
Text(futureSnapshot.data['coname']),
SizedBox(width: 5,),
Text('Category'),
],
),
),
body: Column(
children: [
SizedBox(height: 30,),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(left: 15.0),
child: FlatButton(
onPressed: ()=> _showDialog(),
child: Text('Add Category'),
color: Colors.indigo,
textColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)
),
),
),
],
),
SizedBox(height: 10,),
Divider(),
SizedBox(height: 10,),
Expanded(
child: CategoryWidget(
//futurebuilder snapshot id
futureSnapshot.data.id
),
),
],
),
);
}else{
return Scaffold(
body: Center(child: CircularProgressIndicator()),
);
}
}
);
}
}
Instead of using
String ranDom = randomBetween(0, 300).toString();
Assign a Date and Time(including seconds) to your image name or combination of both ranDom and dateTime.
final ref = FirebaseStorage.instance.ref().child('cars').child(ranDom + DateTime + '.jpg');

How can I update note NoteScreen widget when I add an item in AddNote widget?

In set state I call _notes to fetch notes from firebase to be updated.
But when I add a note in the widget AddNote and press save button, and then go back to NoteScreen, it is not been updated automatically. I must tu swipe down to refresh, and then _notes get again called and the data is up to date.
And I also need feedback on my code, I am a beginner and an opinion about clean code practices will be of high value.
class NoteScreen extends StatefulWidget {
static const routeName = '/noteScreen';
#override
_NoteScreenState createState() => _NoteScreenState();
}
class _NoteScreenState extends State<NoteScreen> {
Widget currentPage;
String search;
bool isLoading = false;
Future<void> _notes() async {
try {
final authData = Provider.of<Auth>(context, listen: false);
await Provider.of<NoteList>(context, listen: false)
.fetchAndSetNotes(search, authData.userId);
print('Note Screen FetchAndSetNotes');
} catch (err) {
print(err.toString());
}
}
#override
void initState() {
_notes();
super.initState();
}
#override
Widget build(BuildContext context) {
final note = Provider.of<NoteList>(context);
print(note.items.length);
SystemChrome.setEnabledSystemUIOverlays([]);
return Scaffold(
resizeToAvoidBottomInset: false,
body: Stack(alignment: Alignment.topCenter, children: <Widget>[
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Colors.teal, Colors.purple])),
child: Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
actions: [
IconButton(
icon: Icon(Icons.add),
onPressed: () {
Navigator.of(context).pushNamed(AddNote.routeName);
},
),
IconButton(
icon: Icon(Icons.logout),
onPressed: () {
Provider.of<Auth>(context, listen: false).logout();
})
],
title: Text(
'NoteApp',
style: TextStyle(fontSize: 20),
),
elevation: 0.0,
backgroundColor: Colors.transparent),
body: SingleChildScrollView(
child: Column(children: [
Align(
alignment: Alignment.topCenter,
child: Container(
height: MediaQuery.of(context).size.height * 0.10,
width: MediaQuery.of(context).size.width,
child: FloatingSearchBar(
borderRadius: BorderRadius.all(Radius.circular(20)),
hint: 'Search',
actions: [],
onQueryChanged: (query) {
setState(() {
try {
search = query;
} catch (err) {
print(err.toString());
}
_notes();
});
},
builder: (context, transition) {
return ClipRRect();
},
),
)),
Align(
alignment: Alignment.bottomCenter,
child: Container(
height: MediaQuery.of(context).size.height * 0.80,
width: MediaQuery.of(context).size.width,
child: FutureBuilder(
builder: (context, snapshot) =>
snapshot.connectionState == ConnectionState.waiting
? CircularProgressIndicator()
: RefreshIndicator(
onRefresh: () => _notes(),
child: ListView.builder(
padding: EdgeInsets.all(10),
itemCount: note.items.length,
itemBuilder: (context, i) => Column(
children: [
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
NoteDisplay(
noteItem: note.items[i],
),
),
);
},
child: note.items[i] != null
? Padding(
padding: EdgeInsets.all(5),
child: NoteItem(
note.items[i].content,
note.items[i].dateTime,
note.items[i].title,
note.items[i].id),
)
: Container(
child: Center(
child: Text(
'No notes Available'),
),
),
),
],
),
),
),
),
),
),
]),
),
)),
]),
);
}
}
**AddNote widget **
class AddNote extends StatefulWidget {
static const routeName = '/addNotes';
#override
_AddNoteState createState() => _AddNoteState();
}
class _AddNoteState extends State<AddNote> {
final _form = GlobalKey<FormState>();
TextEditingController titleControler = new TextEditingController();
var _newNotes = Notes(id: null, title: '', content: '', dateTime: '');
Future<void> _saveNote() async {
final isvalid = _form.currentState.validate();
if (!isvalid) {
return;
}
_form.currentState.save();
Navigator.of(context).pop();
try {
await Provider.of<NoteList>(context, listen: false).addNotes(_newNotes);
print('add_note');
} catch (err) {
print('add_note');
print(err.toString());
}
}
#override
Widget build(BuildContext context) {
final DateTime dateTime = DateTime.now();
String formattedDate = DateFormat('yyyy-MM-dd – kk:mm').format(dateTime);
Size size = MediaQuery.of(context).size;
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Colors.teal, Colors.purple])),
child: Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
elevation: 0.0,
backgroundColor: Colors.transparent,
title: Text('Add notes '),
actions: [IconButton(icon: Icon(Icons.save), onPressed: _saveNote)],
),
body: Center(
child: Form(
key: _form,
child: Container(
height: size.height * 0.7,
margin: EdgeInsets.all(20),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(30))),
child: Card(
margin: EdgeInsets.all(30),
elevation: 20,
child: SingleChildScrollView(
child: Container(
padding: EdgeInsets.all(10),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
TextFormField(
validator: (value) {
if (value.isEmpty) {
return 'Please enter a Title';
}
return null;
},
controller: titleControler,
decoration: InputDecoration(
hintText: 'Title',
),
onSaved: (value) {
_newNotes = Notes(
title: value,
id: _newNotes.id,
content: _newNotes.content,
dateTime: formattedDate);
print(value.toString());
},
textInputAction: TextInputAction.next,
),
SizedBox(
height: 20,
),
TextFormField(
validator: (value) {
if (value.isEmpty) {
return "The content cannon't be empty";
}
return null;
},
onSaved: (value) {
_newNotes = Notes(
title: _newNotes.title,
content: value,
id: _newNotes.id,
dateTime: formattedDate);
print(value.toString());
},
maxLines: null,
keyboardType: TextInputType.multiline,
decoration: InputDecoration(hintText: 'Note content'),
),
SizedBox(
height: 10,
),
Text('$formattedDate')
],
),
),
),
),
),
),
),
),
);
}
}
I believe what is want is a stream instead of a future. i don't know what your fetchAndSetNotes() function looks like but Instead of doing
FirebaseFirestore.instance.collection(collectionName).doc(id).get() you should do Firestore.instance.collection("collectionName").doc(id).snapshots() which will give you a stream. you use a StreamBuilder (considering you are using provider, you should use stream provider) instead of FutureBuilder.

Problems with using a URL in NetworkImage (flutter)

I am trying to pass a URL that I receive from Firebase to my NetworkImage widget on the AppBar. However, my code keeps passing a null value to my NetworkImage widget. How can I pass the URL properly to the widget.
class DashboardScreen extends StatefulWidget {
#override
_DashboardScreenState createState() => _DashboardScreenState();
}
class _DashboardScreenState extends State<DashboardScreen> {
Future inputData() async {
final FirebaseAuth auth = FirebaseAuth.instance;
final FirebaseUser user = await auth.currentUser();
final uid = user.uid;
DocumentReference _stock = Firestore.instance.document('users/$uid');
DocumentSnapshot snapshot = await _stock.get();
Map<String, dynamic> data = snapshot.data;
return data['image_url'];
}
String myAvatarUrl;
void converter() {
inputData().then((result) {
myAvatarUrl = result;
print(myAvatarUrl);
});
}
#override
Widget build(BuildContext context) {
converter();
return Scaffold(
appBar: AppBar(
leading: Padding(
padding: EdgeInsets.only(top: 12.0, bottom: 12.0, left: 13.0),
child: CircleAvatar(
backgroundImage: NetworkImage(myAvatarUrl),
child: FlatButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SearchsettingsScreen(),
),
);
},
),
backgroundColor: Colors.white,
),
),
centerTitle: true,
title: Text(
'My Dashboard',
),
backgroundColor: Theme.of(context).primaryColor,
automaticallyImplyLeading: false,
actions: [
DropdownButton(
underline: Container(),
icon: Icon(
Icons.more_vert,
color: Theme.of(context).primaryIconTheme.color,
),
items: [
DropdownMenuItem(
child: Container(
child: Row(
children: <Widget>[
Icon(
Icons.exit_to_app,
),
SizedBox(
width: 8.0,
),
Text('Logout'),
],
),
),
value: 'logout',
),
],
onChanged: (itemIdentifier) {
if (itemIdentifier == 'logout') {
FirebaseAuth.instance.signOut();
}
},
),
],
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
ReusableDashboardSettingCard(),
ReusableDashboardContactsCard(),
],
),
);
}
}
This is the error I get on my console:
The following assertion was thrown building DashboardScreen(dirty, state: _DashboardScreenState#e1615):
'package:flutter/src/painting/_network_image_io.dart': Failed assertion: line 26 pos 14: 'url != null': is not true.
Your main errors are:
you are not managing that there is the possibility that myAvatarUrl can be null
you are not telling to Flutter to rebuild your widget when data will arrive using setState((){})
I suggest you take a look at Codelabs and Fetch data from the internet.
I've not tested it but it should work
import 'package:flutter/material.dart';
class DashboardScreen extends StatefulWidget {
#override
_DashboardScreenState createState() => _DashboardScreenState();
}
class _DashboardScreenState extends State<DashboardScreen> {
String myAvatarUrl;
Future inputData() async {
final FirebaseAuth auth = FirebaseAuth.instance;
final FirebaseUser user = await auth.currentUser();
final uid = user.uid;
DocumentReference _stock = Firestore.instance.document('users/$uid');
DocumentSnapshot snapshot = await _stock.get();
Map<String, dynamic> data = snapshot.data;
return data['image_url'];
}
#override
void initState() {
super.initState();
// When data will arrive
inputData().then((value) {
setState(() => myAvatarUrl = value);
print(myAvatarUrl);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: myAvatarUrl == null
? const SizedBox()
: Padding(
padding: EdgeInsets.only(top: 12.0, bottom: 12.0, left: 13.0),
child: CircleAvatar(
backgroundImage: NetworkImage(myAvatarUrl),
child: FlatButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SearchsettingsScreen(),
),
);
},
),
backgroundColor: Colors.white,
),
),
centerTitle: true,
title: Text(
'My Dashboard',
),
backgroundColor: Theme.of(context).primaryColor,
automaticallyImplyLeading: false,
actions: [
DropdownButton(
underline: Container(),
icon: Icon(
Icons.more_vert,
color: Theme.of(context).primaryIconTheme.color,
),
items: [
DropdownMenuItem(
child: Container(
child: Row(
children: <Widget>[
Icon(
Icons.exit_to_app,
),
SizedBox(
width: 8.0,
),
Text('Logout'),
],
),
),
value: 'logout',
),
],
onChanged: (itemIdentifier) {
if (itemIdentifier == 'logout') {
FirebaseAuth.instance.signOut();
}
},
),
],
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
ReusableDashboardSettingCard(),
ReusableDashboardContactsCard(),
],
),
);
}
}

NoSuchMethodError: 'dart.global.firebase.auth' in the Flutter Chat App

I was creating this Chat App and after implementing the search function I encountered this NoSuchMethodError: tried to call a non-function, such as null: 'dart.global.firebase.auth' problem.
So basically now when I sign up the email and username doesn't get uploaded to firebase auth and Cloud Firestore, which earlier used to happen I think I did some mistake in the search.dart file which seems weird to me.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:intro/helper/constants.dart';
import 'package:intro/services/database.dart';
import 'package:intro/widgets/widgets.dart';
import 'conversation_screen.dart';
class SearchScreen extends StatefulWidget {
#override
_SearchScreenState createState() => _SearchScreenState();
}
class _SearchScreenState extends State<SearchScreen> {
DatabaseMethods databaseMethods = new DatabaseMethods();
TextEditingController searchTextEditingController =
new TextEditingController();
QuerySnapshot searchSnapshot;
Widget searchList() {
return searchSnapshot != null
? ListView.builder(
itemCount: searchSnapshot.docs.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return searchTile(
searchSnapshot.docs[index].data()["name"],
searchSnapshot.docs[index].data()["email"],
);
})
: Container();
}
initiateSearch() {
databaseMethods
.getUserByUsername(searchTextEditingController.text)
.then((val) {
setState(() {
searchSnapshot = val;
});
});
}
createChatroomAndStartConversation({String userName}) {
String chatRoomId = getChatRoomId(userName, Constants.myName);
List<String> users = [userName, Constants.myName];
Map<String, dynamic> chatRoomMap = {
"users": users,
"chatroomid": chatRoomId
};
DatabaseMethods().createChatRoom(chatRoomId, chatRoomMap);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ConversationScreen(),
));
}
Widget searchTile(String userName, String userEmail) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16),
child: Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(userName, style: mediumTextStyle()),
Text(userEmail, style: mediumTextStyle())
],
),
Spacer(),
GestureDetector(
onTap: () {
createChatroomAndStartConversation(userName: userName);
},
child: Container(
decoration: BoxDecoration(
color: Colors.blue, borderRadius: BorderRadius.circular(30)),
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 6),
child: Text(
"Message",
style: mediumTextStyle(),
),
),
)
],
),
);
}
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: appBarMain(context),
body: Container(
child: Column(
children: [
Container(
color: Color(0x54FFFFFF),
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16),
child: Row(children: [
Expanded(
child: TextField(
controller: searchTextEditingController,
style: TextStyle(
color: Colors.white,
),
decoration: InputDecoration(
hintText: "Search Username",
hintStyle: TextStyle(
color: Colors.white54,
),
border: InputBorder.none),
),
),
GestureDetector(
onTap: () {
initiateSearch();
},
child: Container(
height: 35,
width: 35,
decoration: BoxDecoration(
gradient: LinearGradient(colors: [
const Color(0x36FFFFFF),
const Color(0x0FFFFFFF)
]),
borderRadius: BorderRadius.circular(30)),
padding: EdgeInsets.all(1),
child: Icon(
Icons.search,
color: Colors.white,
)),
)
]),
),
searchList()
],
),
),
);
}
}
getChatRoomId(String a, String b) {
if (a.substring(0, 1).codeUnitAt(0) > b.substring(0, 1).codeUnitAt(0)) {
return "$b\_$a";
} else {
return "$a\_$b";
}
}
and just in case there is an error with the signUp.dart file here it is.
import 'package:flutter/material.dart';
import 'package:intro/helper/helperfunctions.dart';
import 'package:intro/services/auth.dart';
import 'package:intro/services/database.dart';
import 'package:intro/widgets/widgets.dart';
import 'chatRoomsScreen.dart';
class SignUp extends StatefulWidget {
final Function toggle;
SignUp(this.toggle);
#override
_SignUpState createState() => _SignUpState();
}
class _SignUpState extends State<SignUp> {
bool isLoading = false;
AuthMethods authMethods = new AuthMethods();
DatabaseMethods databaseMethods = new DatabaseMethods();
final formKey = GlobalKey<FormState>();
TextEditingController userNameTextEditingController =
new TextEditingController();
TextEditingController emailTextEditingController =
new TextEditingController();
TextEditingController passwordTextEditingController =
new TextEditingController();
signMeUP() {
if (formKey.currentState.validate()) {
Map<String, String> userInfoMap = {
"name": userNameTextEditingController.text,
"email": emailTextEditingController.text,
};
HelperFunctions.saveUserEmailSharedPreference(
emailTextEditingController.text);
HelperFunctions.saveUserNameSharedPreference(
userNameTextEditingController.text);
setState(() {
isLoading = true;
});
authMethods
.signUpwithemailandpassword(emailTextEditingController.text,
passwordTextEditingController.text)
.then((value) {
// print("$value.uid");
databaseMethods.uploadUserInfo(userInfoMap);
HelperFunctions.saveUserLoggedInSharedPreference(true);
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => ChatRoom()));
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: appBarMain(context),
body: isLoading
? Container(
child: Center(child: CircularProgressIndicator()),
)
: SingleChildScrollView(
child: Container(
height: MediaQuery.of(context).size.height - 60,
alignment: Alignment.bottomCenter,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 24),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Form(
key: formKey,
child: Column(
children: [
TextFormField(
validator: (val) {
return val.isEmpty || val.length < 2
? "Invalid Username (Needs to be more than 2 characters)"
: null;
},
controller: userNameTextEditingController,
style: simpleTextStyle(),
decoration: textfieldInputDecoration("username"),
),
TextFormField(
validator: (val) {
return RegExp(
r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+#[a-zA-Z0-9]+\.[a-zA-Z]+")
.hasMatch(val)
? null
: "Enter correct email";
},
controller: emailTextEditingController,
style: simpleTextStyle(),
decoration: textfieldInputDecoration("email"),
),
TextFormField(
obscureText: true,
validator: (val) {
return val.length < 6
? "Please provide with 6+ character"
: null;
},
controller: passwordTextEditingController,
style: simpleTextStyle(),
decoration: textfieldInputDecoration("password"),
),
],
),
),
SizedBox(
height: 10,
),
Container(
alignment: Alignment.centerRight,
child: Container(
padding:
EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Text(
"Forgot Password?",
style: simpleTextStyle(),
),
),
),
SizedBox(
height: 10,
),
GestureDetector(
onTap: () {
signMeUP();
},
child: Container(
alignment: Alignment.center,
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.symmetric(vertical: 20),
decoration: BoxDecoration(
gradient: LinearGradient(colors: [
const Color(0xff007EF4),
const Color(0xff2A75BC)
]),
borderRadius: BorderRadius.circular(30)),
child: Text("Sign Up", style: mediumTextStyle()),
),
),
SizedBox(
height: 10,
),
Container(
alignment: Alignment.center,
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.symmetric(vertical: 20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(30)),
child: Text("Sign Up with Google",
style:
TextStyle(color: Colors.black, fontSize: 18)),
),
SizedBox(
height: 15,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Already have an account? ",
style: mediumTextStyle(),
),
GestureDetector(
onTap: () {
widget.toggle();
},
child: Container(
padding: EdgeInsets.symmetric(vertical: 8),
child: Text(
"Sign in now",
style: TextStyle(
color: Colors.white,
fontSize: 17,
decoration: TextDecoration.underline),
),
),
),
],
),
SizedBox(
height: 50,
)
],
),
),
),
),
);
}
}
And if there is any file anyone of you want: GitHub: Chat App
Because you Haven't initialize the method

No such method error while calling a function

I retrieved products data from Firebase for my E-commerce homepage through future builder. I've created another screen that displays more information on a product when the user clicks on a product from the E-commerce homepage.To navigate to more information screen i created a function called showProduct and called it with a button, but when the button id pressed it shows
NoSuchMethodError: The method '[]' was called on null.Receiver: null Tried calling .
The showProduct function ] was also used on the vendor profile page where the products shown are shown in gridview and when clicked on any product from the vendors's profile.The showProduct function works and open more information screen.
E-commerce Homepage:
c
lass Shop extends StatefulWidget {
final Prod products;
final User currentUser;
final String prodId;
final String onwerId;
Shop({ this.currentUser,
this.prodId,
this.products,
this.onwerId});
#override
_ShopState createState() => _ShopState( prodId: this.prodId,products: this.products,ownerId:this.onwerId);
}
class _ShopState extends State<Shop> {
String postOrientation = "grid";
String shopOrientation = "grid";
bool isFollowing = false;
bool isLoading = false;
String uid="";
String prodId;
String ownerId;
Prod products;
_ShopState({
this.prodId, this.products,this.ownerId,
});
#override
void initState() {
super.initState();
showProduct;
}
Future getProducts()async {
var firestore = Firestore.instance;
QuerySnapshot snap = await firestore.collectionGroup("userProducts").getDocuments();
return snap.documents;
}
Future<Null>getRefresh()async{
await Future.delayed(Duration (seconds : 3));
setState(() {
getProducts();
});
}
showProduct(context) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProductScreen(
prodId: prodId,
userId: ownerId,
),
),
);
}
#override
Widget build(BuildContext context) {
return
Scaffold(
appBar: AppBar(backgroundColor: kSecondaryColor,
title: Text( 'Shop',
style: TextStyle(
fontFamily :"MajorMonoDisplay",
fontSize: 35.0 ,
color: Colors.white),),
iconTheme: new IconThemeData(color: kSecondaryColor),
),
backgroundColor: kPrimaryColor,
body:FutureBuilder(
future: getProducts(),
builder: (context,snapshot)
{
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: circularProgress(),);
} else {
return
RefreshIndicator(
onRefresh: getRefresh,
child: ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
var ourdata = snapshot.data[index];
return
Container(
height: 500,
margin: EdgeInsets.only(
top: 1.0, left: 10.0, right: 10.0, bottom: 1.0),
child: Column( children: <Widget>[
SizedBox( height:1.0,),
Stack(
children: <Widget>[
Container(
child:Row(
children: <Widget>[
Expanded(
child: Container(
height: 400.0,
child: ClipRRect(borderRadius: BorderRadius.circular(20.0),
child: cachedNetworkImage(ourdata.data['shopmediaUrl'],
),
),
),
),
],
),
),
Expanded(
child: Positioned(
bottom: 10,
left: 10,
child: Container(
height: 40,
width: 40,
child: ClipRRect(
borderRadius: BorderRadius.circular(40.0),
child: Image.network(ourdata.data['photoUrl'],)),
),
),
),
Expanded(
child: Positioned(
bottom: 20,
left: 60,
child: Container(
child: Text(ourdata.data['username'],style: TextStyle(color: Colors.white,fontWeight:FontWeight.bold),),
),
),
),
Container(
alignment: Alignment.bottomRight,
child: GFButton(
onPressed: () => showProduct(context) ,
text: "More",
icon: Icon(Icons.card_travel),
shape: GFButtonShape.pills,
),
),
],
),
Row(
children: <Widget>[
Container(
child: Text(ourdata.data['productname'],style: TextStyle(color: kText,fontSize: 30.0,fontWeight:FontWeight.bold),),
),
],
),
Row(
children: <Widget>[
Container( child: Text('₹',style: TextStyle(color: kText,)),
),
Container(
child: Text(ourdata.data['price'],style: TextStyle(color: kText,fontSize: 20.0,fontWeight:FontWeight.bold),),
),
],
),
Divider(color: kGrey,),
],
),
);
}
)
);
}
}
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.black38,
onPressed: ()
async{ Navigator.push(context, MaterialPageRoute(builder: (context) =>Uploadecom(currentUser: currentUser, )));
},
child: Icon(Icons.add_box),
),
);
}
}
This is the gridview on the vendor's profile.
class ProductTile extends StatelessWidget {
final Prod products;
ProductTile(this.products);
showProduct(context) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProductScreen(
prodId: products.prodId,
userId: products.ownerId,
),
),
);
}
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => showProduct(context),
child: cachedNetworkImage(products.shopmediaUrl),
);
}
}
If you need more codes please ask me.

Resources