【问题标题】:Update Flutter UI after changing data on Firebase Firestore更改 Firebase Firestore 上的数据后更新 Flutter UI
【发布时间】:2021-06-27 07:15:48
【问题描述】:

我有一个应用程序,其个人资料页面包含用户名、电子邮件和个人资料图片。

我想要做的是,用户单击一个按钮来更改个人资料图片,打开一个带有简单圆形头像小部件和一个按钮的新页面,该页面会将图像上传到 Firebase Storage 和 Firebase Firestore,添加到该特定当前用户 uid 的 Firestore 集合。

一切正常,我可以看到 Firebase 存储上的变化,由 uid + 当前用户集合上的 URL 添加的图像。

这是edit_user_image_screen的代码:

import 'dart:io';

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:tradie_app/scr/providers/authService.dart';
import 'package:tradie_app/scr/widgets/loading.dart';

class EditCompanyImageScreen extends StatefulWidget {
  @override
  _EditCompanyImageScreenState createState() => _EditCompanyImageScreenState();
}

class _EditCompanyImageScreenState extends State<EditCompanyImageScreen> {
  // Keep track of the form for validation
  final _formKey = GlobalKey<FormState>();

  // Loading Icon
  bool loading = false;

  final AuthService _authService = AuthService();
  final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
  final FirebaseFirestore _firebaseFirestore = FirebaseFirestore.instance;

  File _image;

  Future getImage(bool gallery) async {
    ImagePicker picker = ImagePicker();
    PickedFile pickedFile;
    // Let user select photo from gallery
    if (gallery) {
      pickedFile = await picker.getImage(
        source: ImageSource.gallery,
      );
    }
    setState(() {
      if (pickedFile != null) {
        _image = File(pickedFile.path);
        uploadFile(_image); // Use if you only need a single picture
      } else {
        print('No image selected.');
      }
    });
  }

  Future<String> uploadFile(File image) async {
    String downloadURL;
    Reference ref = FirebaseStorage.instance
        .ref()
        .child("images/${_firebaseAuth.currentUser.uid}");
    await ref.putFile(image);
    downloadURL = await ref.getDownloadURL();
    return downloadURL;
  }

  Future uploadToFirebase() async {
    final CollectionReference users =
        _firebaseFirestore.collection("Companies");
    final String uid = _firebaseAuth.currentUser.uid;

    String url = await uploadFile(
        _image); // this will upload the file and store url in the variable 'url'
    await users.doc(uid).update({'url': url});
    final result = await users.doc(uid).get();
    return result.data()["url"];
  }

  @override
  Widget build(BuildContext context) {
    return loading
        ? Loading()
        : Scaffold(
            appBar: AppBar(
              title: Text("Update Profile Image"),
            ),
            body: Form(
              key: _formKey,
              child: Column(
                children: [
                  Container(
                    child: Stack(
                      children: <Widget>[
                        Align(
                          alignment: Alignment.center,
                          child: IconButton(
                            icon: Icon(Icons.camera_alt),
                            onPressed: () async {
                              getImage(true);
                            },
                          ),
                        ),
                        Container(
                          child: _image != null
                              ? Container(
                                  height: 200,
                                  width: 200,
                                  decoration: BoxDecoration(
                                    image: DecorationImage(
                                        image: FileImage(
                                          _image,
                                        ),
                                        fit: BoxFit.contain),
                                  ),
                                )
                              : Container(
                                  decoration: BoxDecoration(
                                    color: Colors.grey[200],
                                    borderRadius: BorderRadius.circular(50),
                                  ),
                                  width: 100,
                                  height: 100,
                                  child: Icon(
                                    Icons.camera_alt,
                                    color: Colors.grey[800],
                                  ),
                                ),
                        ),
                      ],
                    ),
                  ),
                  Row(
                    children: [
                      ElevatedButton(
                        style: ElevatedButton.styleFrom(
                          primary: Colors.black,
                        ),
                        child: Text(
                          "Submit",
                          style: TextStyle(color: Colors.white),
                        ),
                        onPressed: () async {
                          uploadToFirebase();
                          Navigator.pop(context);
                        },
                      ),
                    ],
                  ),
                ],
              ),
            ),
          );
  }
}

在 company_profile_screen 上,我有这段代码:

Stream getCompanyImageData() async* {
    final CollectionReference users =
        _firebaseFirestore.collection("Companies");
    final String uid = _firebaseAuth.currentUser.uid;
    final result = await users.doc(uid).get();
    yield result.data()["url"];
  }

我的问题:

当我从 edit_user_image_screen 回到 company_screen 时,App UI 没有更新,我可以在 Firebase 上看到更改,如果我重新加载 Android Studio,我可以在 UI 上看到更改,但不是自动的。

这是我在 company_screen 上显示图像的代码:

Column(
    children: [
                                  StreamBuilder(
                                    stream: getCompanyImageData(),
                                    builder: (BuildContext context,
                                        AsyncSnapshot snapshot) {
                                      if (snapshot.connectionState ==
                                          ConnectionState.waiting) {
                                        return Center(
                                          child: CircularProgressIndicator(),
                                        );
                                      }
                                      return Image.network(
                                        snapshot.data.toString(),
                                        width: 100,
                                        height: 100,
                                      );
                                    },
                                  ),
                                ],
                              ),

【问题讨论】:

    标签: firebase flutter user-interface google-cloud-firestore


    【解决方案1】:

    试试这样,取消你的顶级功能getCompanyImageData()

    Column(children: [
          StreamBuilder(
            stream: _firebaseFirestore.collection("Companies").doc(_firebaseAuth.currentUser.uid).snapshots(),
            builder: (BuildContext context, AsyncSnapshot snapshot) {
              if (snapshot.connectionState == ConnectionState.waiting) {
                return Center(
                  child: CircularProgressIndicator(),
                );
              }
              return Image.network(
                snapshot.data.data()["url"],
                width: 100,
                height: 100,
              );
            },
          ),
    

    【讨论】:

    • 你用过这个Image.network(snapshot.data.data()["url"], 吗?我将它包含在我的答案中,也许你错过了它。
    • 嘿,谢谢,它成功了!但是,更改图像的过程有点慢。还有,这部分:snapshot.data.data()["url"],data.data,是不是故意的?
    • 快照是您的直播结果。第一个data 是如果流有任何数据,第二个data() 是解锁文档快照。如果你print(snapshot.data),你会得到instance of DocumentSnapshot,如果你print(snapshot.data.data()),你会得到你的物品的地图,即{“url”:“example.come”}。它很慢,但更像是在图像到达时呈现图像
    • 13 秒是很长的时间,有些东西是关闭的,除非您使用的是大图像文件。图片的尺寸是多少?
    • Firebase 超级快,关于上传下载,我从来没有遇到过任何问题。将它用于具有大量图像的市场应用程序。您每页要处理多少张图片?
    【解决方案2】:

    这将取决于您的状态管理,

    CollectionRef.users.doc(ViewModelUser.user.value.mobile).snapshots().listen((event) {
          ViewModelUser.setUser(UserModel.fromJson(event.data()));
        });
    

    这是我的代码,用于监听我的个人资料中的更改,当有更改时,firebase 会向我发送更新的数据并更新我的 userData,我的状态管理会完成更新 UI 的其余工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-07-19
      • 2023-03-30
      • 1970-01-01
      • 2023-03-19
      • 1970-01-01
      • 2021-08-14
      • 1970-01-01
      相关资源
      最近更新 更多