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

Flutter中RatingBar评分存入Firestore始终为5的问题求助

Flutter评分存储问题:选择任意评分始终存入5星的解决方案

enter image description here
enter image description here

我在Flutter项目中遇到问题:无论选择1-5星中的任意评分,提交后Firestore数据库中始终存储为5,尝试多种方法均未解决,恳请帮助。

评分存储流程涉及三个模块:Review页面传递值至ReviewController,再由其传递至ReviewService存入数据库,相关代码如下:

Review页面代码

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_rating_bar/flutter_rating_bar.dart';

import 'package:get/get.dart';
import 'package:hallo_doctor_client/app/modules/widgets/submit_button.dart';

import '../controllers/review_controller.dart';

class ReviewView extends GetView<ReviewController> {
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
      child: Scaffold(
        appBar: AppBar(
          title: Text('Review Doctor'.tr),
          centerTitle: true,
        ),
        body: SingleChildScrollView(
          child: Container(
            width: double.infinity,
            padding: EdgeInsets.all(10),
            child: Card(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  ListTile(
                    leading: CircleAvatar(
                      radius: 40,
                      backgroundImage: CachedNetworkImageProvider(
                          controller.timeSlot.doctor!.doctorPicture!),
                    ),
                    title: Text(controller.timeSlot.doctor!.doctorName!),
                  ),
                  Divider(),
                  TextField(
                    controller: controller.textEditingReviewController,
                    decoration: InputDecoration(
                        border: OutlineInputBorder(),
                        hintText: 'Your Review'.tr),
                    maxLines: 10,
                    textInputAction: TextInputAction.done,
                    onSubmitted: (value) => controller.review = value,
                  ),
                  Divider(),
                  Obx(() => RatingBar.builder(
                        initialRating: controller.rating.value,
                        minRating: 1,
                        direction: Axis.horizontal,
                        allowHalfRating: true,
                        itemCount: 5,
                        itemPadding: EdgeInsets.symmetric(horizontal: 4.0),
                        itemBuilder: (context, _) => Icon(
                          Icons.star,
                          color: Colors.amber,
                        ),
                        onRatingUpdate: (rating) {
                          FocusManager.instance.primaryFocus?.unfocus();
                          print(rating);
                        },
                      )),
                  SizedBox(
                    height: 50,
                  ),
                  SubmitButton(
                      onTap: () {
                        controller.saveReiew();
                      },
                      text: "Send".tr)
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

核心RatingBar组件

Obx(() => RatingBar.builder(
      initialRating: controller.rating.value,
      minRating: 1,
      direction: Axis.horizontal,
      allowHalfRating: true,
      itemCount: 5,
      itemPadding: EdgeInsets.symmetric(horizontal: 4.0),
      itemBuilder: (context, _) => Icon(
        Icons.star,
        color: Colors.amber,
      ),
      onRatingUpdate: (rating) {
        FocusManager.instance.primaryFocus?.unfocus();
        print(rating);
      },
    )),

ReviewController代码

import 'package:flutter/cupertino.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:get/get.dart';
import 'package:hallo_doctor_client/app/models/time_slot_model.dart';
import 'package:hallo_doctor_client/app/service/review_service.dart';
import 'package:hallo_doctor_client/app/service/user_service.dart';

class ReviewController extends GetxController {
  //TODO: Implement ReviewController

  var review = '';
  var rating = 5.0.obs;
  TextEditingController textEditingReviewController = TextEditingController();
  TimeSlot timeSlot = Get.arguments;
  var price = 0.obs;
  var ratings = '';
  @override
  void onInit() {
    super.onInit();
    price.value = timeSlot.price!;
  }

  @override
  void onClose() {}
  void saveReiew() async {
    EasyLoading.show(maskType: EasyLoadingMaskType.black);
    var user = UserService().currentUserFirebase;
    try {
      await ReviewService().saveReview(textEditingReviewController.text,
          rating.value.toInt(), timeSlot, user!);
      Get.close(2);
      //Get.back();
    } catch (e) {
      Fluttertoast.showToast(msg: e.toString());
    } finally {
      EasyLoading.dismiss();
    }
  }
}

ReviewService代码

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:hallo_doctor_client/app/models/doctor_model.dart';
import 'package:hallo_doctor_client/app/models/review_model.dart';
import 'package:hallo_doctor_client/app/models/time_slot_model.dart';
import 'package:hallo_doctor_client/app/service/user_service.dart';

class ReviewService {
  Future saveReview(
      String review, int rating, TimeSlot timeSlot, User user) async {
    try {
      await FirebaseFirestore.instance
          .collection('Review')
          .doc(timeSlot.timeSlotId)
          .set({
        'review': review,
        'rating': rating,
        'timeSlotId': timeSlot.timeSlotId,
        'userId': UserService().currentUserFirebase!.uid,
        'doctorId': timeSlot.doctorid,
        'user': {
          'displayName': UserService().currentUserFirebase!.displayName,
          'photoUrl': UserService().getProfilePicture(),
        }
      });


    } catch (e) {
      return Future.error(e.toString());
    }
  }

  Future<List<ReviewModel>> getDoctorReview(
      {required Doctor doctor, int limit = 4}) async {
    try {
      var reviewRef = await FirebaseFirestore.instance
          .collection('Review')
          .where('doctorId', isEqualTo: doctor.doctorId)
          .limit(limit)
          .get();
      List<ReviewModel> listReview = reviewRef.docs.map((doc) {
        var data = doc.data();
        data['reviewId'] = doc.reference.id;
        ReviewModel review = ReviewModel.fromMap(data);
        return review;
      }).toList();
      return listReview;
    } catch (e) {
      return Future.error(e.toString());
    }
  }
}

问题根源与修复方法

问题出在RatingBar的onRatingUpdate回调中:仅打印了评分值,但没有更新ReviewController中rating这个可观察变量,导致提交时始终使用初始值5存入数据库。

只需修改RatingBar的onRatingUpdate回调,添加更新controller.rating的代码即可:

onRatingUpdate: (rating) {
  FocusManager.instance.primaryFocus?.unfocus();
  print(rating);
  // 新增此行,更新控制器中的评分变量
  controller.rating.value = rating;
},

修改后,用户选择的评分会同步更新到controller的rating变量中,提交时就能将正确的评分传入ReviewService,最终存入Firestore数据库。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 21:59:59