firebase - 使用 firebase 在 listview 中显示所有用户图像
问题描述
在我的应用程序中,任何用户都可以添加广告,并且在主屏幕中,所有广告都显示在列表视图中,我从 firebase 的汽车表中获取每个广告的信息;但我想通过发送用户 ID 并从用户表中获取图像来显示该用户的个人资料图像。
我从 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
再次调用该方法,并发出网络请求并再次调用该build
方法......
您可以通过使用FutureBuilder获取数据来解决此问题。按着这些次序:
- 更新
getimage
方法以返回图像 url 而不是更改状态:
Future<String> getimage() async {
var res = await carobj.getAdData(carUserId);
return (res.data() as Map)['imgPro'].toString();
}
- 声明一个变量
_imageFuture
来保存getimage
网络请求的结果:
Future<String> _imageFuture;
- 将
getimage
方法分配_imageFuture
给initState
:
@override
void initState() {
...
_imageFuture = getimage();
}
- 更新
ListTile
以使用FutureBuilder
从以下获取图像的a_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
)
),
),
);
}
}
),
),
)
推荐阅读
- python-3.x - 内部错误:Blas GEMV 启动失败:m=4,n=800 [[{{node PartitionedCall/MatMul}}]] [Op:__inference_train_97]
- java - Android游戏中runOnUiThread的目的是什么?
- python - Django 不一致迁移历史
- wordpress - 在自定义帖子类型中添加额外的文件
- angular - 在 Angular 中分离模块会使其更快吗?
- asp.net - 需要从 Asp.Net 中的当前日期开始的上个月的第一天和下个月的最后一天
- google-cloud-platform - `gcloud compute instances create-with-container --public-dns` - 这是做什么的?
- android - Presenter 方法和回调的圈复杂度计算
- python - Python 3.8 - 试图将我的随机数保存到变量中
- youtube - 您如何使用 youtube-dl 录制直播的早期部分?