You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Firebase数据更新失败问题求助(2021年)

Hey there! Let's break down why your Firebase update isn't working and fix it step by step—there are a couple of straightforward issues in your code that are blocking the update.

Key Problems in Your Current Code

1. You're passing TextEditingController objects instead of their text values

In your ElevatedButton's onPressed handler, you're trying to save controller instances (like TextEditingController(text: x['firstName'])) to Firebase instead of the actual text the user entered. Firebase expects string values, not controller objects, so this won't work at all.

2. Creating TextEditingControllers inside the StreamBuilder builder function

Every time the StreamBuilder rebuilds (which happens when Firebase data updates or the UI refreshes), you create brand new controllers. This means you lose any user input and can't reference the updated text when you try to save changes.

Fixed Code Implementation

First, convert your widget to a StatefulWidget so you can persist controllers across rebuilds. Here's the revised code with fixes:

class ProfileEditWidget extends StatefulWidget {
  const ProfileEditWidget({super.key});

  @override
  State<ProfileEditWidget> createState() => _ProfileEditWidgetState();
}

class _ProfileEditWidgetState extends State<ProfileEditWidget> {
  // Initialize controllers at the state level
  late TextEditingController _firstNameController;
  late TextEditingController _lastNameController;
  late TextEditingController _middleNameController;
  late TextEditingController _phoneController;
  String? _profileDocId; // Store document ID dynamically (no hardcoding!)

  @override
  void initState() {
    super.initState();
    // Initialize empty controllers
    _firstNameController = TextEditingController();
    _lastNameController = TextEditingController();
    _middleNameController = TextEditingController();
    _phoneController = TextEditingController();
  }

  @override
  void dispose() {
    // Clean up controllers to avoid memory leaks
    _firstNameController.dispose();
    _lastNameController.dispose();
    _middleNameController.dispose();
    _phoneController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<QuerySnapshot>(
      stream: FirebaseFirestore.instance.collection("personalDetail").snapshots(),
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          // Get the first profile document
          final profileDoc = snapshot.data!.docs.first;
          _profileDocId = profileDoc.id; // Capture document ID dynamically

          // Update controller text only if it doesn't match the latest Firebase data
          if (_firstNameController.text != profileDoc['firstName']) {
            _firstNameController.text = profileDoc['firstName'];
          }
          if (_lastNameController.text != profileDoc['lastName']) {
            _lastNameController.text = profileDoc['lastName'];
          }
          if (_middleNameController.text != profileDoc['middleName']) {
            _middleNameController.text = profileDoc['middleName'];
          }
          if (_phoneController.text != profileDoc['phone']) {
            _phoneController.text = profileDoc['phone'];
          }

          return ListView.builder(
            itemCount: 1,
            itemBuilder: (context, index) {
              return Container(
                padding: EdgeInsets.all(16),
                child: Column(
                  children: [
                    // Your avatar stack code remains the same
                    Center(
                      child: Stack(
                        children: [
                          Container(
                            width: 130,
                            height: 130,
                            decoration: BoxDecoration(
                              border: Border.all(width: 4, color: Colors.white),
                              boxShadow: [
                                BoxShadow(
                                  spreadRadius: 2,
                                  blurRadius: 10,
                                  color: Colors.black.withOpacity(0.1),
                                )
                              ],
                              shape: BoxShape.circle,
                              image: DecorationImage(
                                fit: BoxFit.cover,
                                image: AssetImage('assets/images/Profile.jpg'),
                              ),
                            ),
                          ),
                          Positioned(
                            bottom: 0,
                            right: 0,
                            child: Container(
                              height: 40,
                              width: 40,
                              decoration: BoxDecoration(
                                shape: BoxShape.circle,
                                border: Border.all(width: 4, color: Colors.white),
                                color: Colors.green.shade400
                              ),
                              child: Icon(Icons.camera_alt, color: Colors.white),
                            ),
                          )
                        ],
                      ),
                    ),
                    SizedBox(height: 30),
                    // Updated TextFormFields using persistent controllers
                    TextFormField(
                      maxLength: 20,
                      style: TextStyle(color: Colors.black, fontSize: 15),
                      controller: _firstNameController,
                      decoration: InputDecoration(
                        labelText: "First Name",
                        labelStyle: TextStyle(
                          fontWeight: FontWeight.w800,
                          color: Colors.black,
                          fontSize: 23),
                        floatingLabelBehavior: FloatingLabelBehavior.always,
                      ),
                    ),
                    TextFormField(
                      maxLength: 20,
                      style: TextStyle(color: Colors.black, fontSize: 15),
                      controller: _lastNameController,
                      decoration: InputDecoration(
                        labelText: "Last Name",
                        labelStyle: TextStyle(
                          fontWeight: FontWeight.w800,
                          color: Colors.black,
                          fontSize: 23),
                        floatingLabelBehavior: FloatingLabelBehavior.always,
                      ),
                    ),
                    TextFormField(
                      maxLength: 15,
                      style: TextStyle(color: Colors.black, fontSize: 15),
                      controller: _middleNameController,
                      decoration: InputDecoration(
                        labelText: "Middle Name",
                        labelStyle: TextStyle(
                          fontWeight: FontWeight.w800,
                          color: Colors.black,
                          fontSize: 23),
                        floatingLabelBehavior: FloatingLabelBehavior.always,
                      ),
                    ),
                    TextFormField(
                      maxLength: 10,
                      keyboardType: TextInputType.phone,
                      inputFormatters: [FilteringTextInputFormatter.digitsOnly],
                      style: TextStyle(color: Colors.black, fontSize: 15),
                      controller: _phoneController,
                      decoration: InputDecoration(
                        labelText: "Phone Number",
                        labelStyle: TextStyle(
                          fontWeight: FontWeight.w800,
                          color: Colors.black,
                          fontSize: 23),
                        floatingLabelBehavior: FloatingLabelBehavior.always,
                      ),
                    ),
                    TextFormField(
                      initialValue: profileDoc['email'],
                      enabled: false,
                      style: TextStyle(color: Colors.black, fontSize: 15),
                      decoration: InputDecoration(
                        labelText: "Email",
                        labelStyle: TextStyle(
                          fontWeight: FontWeight.w800,
                          color: Colors.black,
                          fontSize: 23),
                        floatingLabelBehavior: FloatingLabelBehavior.always,
                      ),
                    ),
                    SizedBox(height: 30),
                    Align(
                      child: ElevatedButton(
                        onPressed: () async {
                          if (_profileDocId == null) {
                            Fluttertoast.showToast(
                              msg: "No profile data found",
                              toastLength: Toast.LENGTH_SHORT,
                              gravity: ToastGravity.BOTTOM,
                              textColor: Colors.white,
                              backgroundColor: Colors.red.shade400,
                            );
                            return;
                          }

                          try {
                            // Update Firebase with controller text values
                            await FirebaseFirestore.instance
                                .collection('personalDetail')
                                .doc(_profileDocId)
                                .update({
                              "firstName": _firstNameController.text,
                              "lastName": _lastNameController.text,
                              "middleName": _middleNameController.text,
                              "phone": _phoneController.text,
                            });

                            Fluttertoast.showToast(
                              msg: "Profile updated Successfully",
                              toastLength: Toast.LENGTH_SHORT,
                              gravity: ToastGravity.BOTTOM,
                              textColor: Colors.black,
                              backgroundColor: Colors.green.shade400,
                            );
                            Navigator.pushNamed(context, "/profilePage");
                          } catch (e) {
                            // Handle update errors (e.g., network issues)
                            Fluttertoast.showToast(
                              msg: "Update failed: ${e.toString()}",
                              toastLength: Toast.LENGTH_LONG,
                              gravity: ToastGravity.BOTTOM,
                              textColor: Colors.white,
                              backgroundColor: Colors.red.shade400,
                            );
                          }
                        },
                        child: Text(
                          "Save Details",
                          style: TextStyle(
                            fontSize: 15,
                            letterSpacing: 2,
                            color: Colors.black),
                        ),
                        style: ElevatedButton.styleFrom(
                          fixedSize: Size(250, 40),
                          backgroundColor: Colors.green.shade500,
                          padding: EdgeInsets.symmetric(horizontal: 50),
                          shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(10))),
                      ),
                    )
                  ],
                ),
              );
            },
          );
        } else if (snapshot.hasError) {
          return Center(child: Text("Error loading profile: ${snapshot.error}"));
        } else {
          return Center(child: CircularProgressIndicator());
        }
      },
    );
  }
}

Additional Improvements

  • No hardcoded document ID: We now capture the document ID directly from the snapshot, so you don't have to update code if your document ID changes.
  • Error handling: Added try/catch to handle network errors or Firebase permissions issues, so users get clear feedback if something goes wrong.
  • Memory management: Controllers are properly disposed of in the dispose method to avoid memory leaks.

Give these changes a try—this should resolve your update issue completely. Let me know if you run into any other roadblocks!

内容的提问来源于stack exchange,提问作者user17112368

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 17:42:34