首页 > 解决方案 > 使用 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
                          )
                        ),
                      ),
                    ) ,

代码输出:

代码的输出

标签: firebaseflutterfirebase-realtime-databaseflutter-web

解决方案


您正在获得这种行为,因为您正在调用setStatebuild 方法。这会导致build再次调用该方法,并发出网络请求并再次调用该build方法......

您可以通过使用FutureBuilder获取数据来解决此问题。按着这些次序:

  1. 更新getimage方法以返回图像 url 而不是更改状态:
Future<String> getimage() async {
  var res = await carobj.getAdData(carUserId);
  return (res.data() as Map)['imgPro'].toString();
}
  1. 声明一个变量_imageFuture来保存getimage网络请求的结果:
Future<String> _imageFuture;
  1. getimage方法分配_imageFutureinitState
@override
  void initState() {
    ...
    _imageFuture = getimage();
}
  1. 更新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
                )
              ),
            ),
          );
        }
      }
    ),
  ),
)

推荐阅读