使用 firebase 在 listview 中显示所有用户图像
Posted
技术标签:
【中文标题】使用 firebase 在 listview 中显示所有用户图像【英文标题】:showing all users images in listview with firebase 【发布时间】:2021-11-03 07:36:33 【问题描述】:在我的应用程序中,任何用户都可以添加广告,并且在主屏幕中,所有广告都显示在列表视图中,我从 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
)
),
),
) ,
代码输出:
【问题讨论】:
【参考方案1】:你得到这个行为是因为你在 build 方法中调用了setState
。这会导致再次调用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
方法分配给initState
中的_imageFuture
:
@override
void initState()
...
_imageFuture = getimage();
-
更新
ListTile
以使用从_imageFuture
获取图像的FutureBuilder
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
)
),
),
);
),
),
)
【讨论】:
tnx 但是我应该在哪里获取汽车用户 ID? bcz cra 用户 ID 必须来自当前列表项,所以我假设我必须在构建中获取它! 问题对您来说是解决方案,但略有不同。我只是在 ListView.builder=>itemBuilder 中调用(`_imageFuture = getimage();`) 我不知道这样做的权利,但它是工作以上是关于使用 firebase 在 listview 中显示所有用户图像的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Firebase 查询的结果最终在 Android Studio 中填充 ListView
如何使用 firebase 获取 listView 中每个项目的数据?
使用Firebase时,ListView仅在onCreate()方法中更新