Flutter中RatingBar评分存入Firestore始终为5的问题求助
Flutter评分存储问题:选择任意评分始终存入5星的解决方案


我在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
相关产品推荐
相关产品推荐

