使用 firebase 在列表视图中显示所有用户图像
showing all users images in listview with firebase
在我的应用程序中,任何用户都可以添加广告,并且在主屏幕中,所有广告都显示在列表视图中,我从 firebase 中的 table 汽车中获取每个广告的信息;但我想通过发送用户 ID 并从用户 table.
获取图像来显示该用户的个人资料图像
我从 firebase 获取数据的函数:
Future<DocumentSnapshot> getAdData(String uid)async{
return await FirebaseFirestore.instance.collection('users').doc(uid).
get();
}
我的主屏幕:
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();
},
),
);
}
}
我在哪里获取图像(来自主屏幕代码):
getimage()async{
await carobj.getAdData(carUserId).then((res){
setState(() {
usersImg=(res.data() as Map)['imgPro'].toString();
});
});
}
我在哪里将图像设置为列表视图(来自主屏幕代码):
@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
)
),
),
) ,
代码输出:
您出现此行为是因为您在构建方法中调用了 setState
。这会导致再次调用 build
方法,它会发出网络请求并再次调用 build
方法...
您可以通过使用 FutureBuilder 获取数据来解决此问题。请按照以下步骤操作:
- 将
getimage
方法更新为 return 图像 url 而不是更改状态:
Future<String> getimage() async {
var res = await carobj.getAdData(carUserId);
return (res.data() as Map)['imgPro'].toString();
}
- 声明一个变量
_imageFuture
来保存getimage
网络请求的结果:
Future<String> _imageFuture;
- 将
getimage
方法分配给 initState
中的 _imageFuture
:
@override
void initState() {
...
_imageFuture = getimage();
}
- 更新
ListTile
以使用从 _imageFuture
Future
: 获取图像的 FutureBuilder
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
)
),
),
);
}
}
),
),
)
在我的应用程序中,任何用户都可以添加广告,并且在主屏幕中,所有广告都显示在列表视图中,我从 firebase 中的 table 汽车中获取每个广告的信息;但我想通过发送用户 ID 并从用户 table.
获取图像来显示该用户的个人资料图像我从 firebase 获取数据的函数:
Future<DocumentSnapshot> getAdData(String uid)async{
return await FirebaseFirestore.instance.collection('users').doc(uid).
get();
}
我的主屏幕:
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();
},
),
);
}
}
我在哪里获取图像(来自主屏幕代码):
getimage()async{
await carobj.getAdData(carUserId).then((res){
setState(() {
usersImg=(res.data() as Map)['imgPro'].toString();
});
});
}
我在哪里将图像设置为列表视图(来自主屏幕代码):
@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
)
),
),
) ,
代码输出:
您出现此行为是因为您在构建方法中调用了 setState
。这会导致再次调用 build
方法,它会发出网络请求并再次调用 build
方法...
您可以通过使用 FutureBuilder 获取数据来解决此问题。请按照以下步骤操作:
- 将
getimage
方法更新为 return 图像 url 而不是更改状态:
Future<String> getimage() async {
var res = await carobj.getAdData(carUserId);
return (res.data() as Map)['imgPro'].toString();
}
- 声明一个变量
_imageFuture
来保存getimage
网络请求的结果:
Future<String> _imageFuture;
- 将
getimage
方法分配给initState
中的_imageFuture
:
@override
void initState() {
...
_imageFuture = getimage();
}
- 更新
ListTile
以使用从_imageFuture
Future
: 获取图像的
FutureBuilder
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
)
),
),
);
}
}
),
),
)