使用 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

使用Firebase时,ListView仅在onCreate()方法中更新

在Android中更新firebase数据库时ListView值重复值

如何从 Firebase 检索数据到 ListView(使用自定义数组适配器)