如何在 flutter 评分栏中保存用户评分?

How to save User rating in flutter rating bar?

我正在尝试保存用户评分,以便在用户返回页面时显示它。但我有点挣扎,不知道该怎么做。评级有效,但正如我所说,储蓄无效。 所以发生的事情是它总是空的。我真正想要的是,如果用户返回页面,他会看到他的评分,如果他再次评分并且评分不同,我让他评分的最后一个评分,如果没有,则不,如果他按清除,评分将被删除也很好用。

也许任何人都可以提供帮助。

lass Ratingpage extends StatefulWidget {
  final int maximumRating;
  final Function(int) onRatingSelected;

  Ratingpage(this.onRatingSelected, [this.maximumRating = 5]);

  @override
  _RatingpageState createState() => _RatingpageState();
}

class _RatingpageState extends State<Ratingpage> {
  int haveusercurrentchoice;

  int _currentRating = 0;

  Widget _buildRatingStar(int index) {
    if (index < _currentRating) {
      return Icon(
        Icons.star,
        color: Colors.yellow,
      );
    } else {
      return Icon(
        Icons.star,
        color: Colors.white,
      );
    }
  }

  Widget _buildBody() {
    final stars = List<Widget>.generate(this.widget.maximumRating, (index) {
      return Expanded(
        child: GestureDetector(
          child: _buildRatingStar(index),
          onTap: () {
            setState(() {
              _currentRating = index;
            });

            this.widget.onRatingSelected(_currentRating);
          },
        ),
      );
    });
    return Row(
      children: [
        Expanded(
          child: Row(
            children: stars,
          ),
        ),
        Expanded(
          child: TextButton(
            onPressed: () {
              setState(() {
                _currentRating = 0;
              });

              this.widget.onRatingSelected(_currentRating);
            },
            child: Text(
              "Clear",
              style: TextStyle(color: Colors.white),
            ),
          ),
        ),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return _buildBody();
  }

如果您需要更多信息,请发表评论。

这就是我调用页面的方式

 Container(
                                width: 210,
                                height: 94,
                                //color: Colors.blue.withOpacity(0.5),
                                child: Column(
                                  children: [
                                    InkWell(
                                      onTap: () {
                                        setState(() {
                                          israting = true;
                                        });
                                        //  if( _rating !=null && _rating >0){
                                        // likevideo(videos.data()['id']);}
                                      },
                                      child: israting
                                          ? Container(
                                              height: 50,
                                              margin: EdgeInsets.fromLTRB(
                                                  0, 0, 5, 0),
                                              child: Column(
                                                children: [
                                                  Ratingpage((rating) {
                                                    setState(() {
                                                      _rating = rating;
                                                    });

                                                    if (_rating != null &&
                                                        _rating > 0) {
                                                      likevideo(
                                                          videos.data()['id'],
                                                          _rating);

                                                      print(delteuserchoicing);
                                                    } else if (_rating ==
                                                            null ||
                                                        _rating == 0) {
                                                      dislike(
                                                          videos.data()['id'],
                                                          _rating);
                                                    }
                                                  }),
                                                ],
                                              ),
                                            )
                                          : Icon(
                                              Icons.star,
                                              size: 37,
                                              color: videos
                                                      .data()['likes']
                                                      .contains(uid)
                                                  ? Colors.yellow
                                                  : Colors.white,
                                            ),
                                    ),

其实是在一列里面

所以您在页面之间存储状态时遇到问题,然后在应用重启时存储评分时遇到问题。 2个独立的东西。您可能只关心前者,但这里是您如何使用 GetX State management and GetStorage 进行本地数据库存储。同样的事情可以用任何其他状态管理解决方案来完成,即。 Provider、Riverpod、Bloc 等...

GetStorage 可与 SharedPreferences 互换,但我认为任何使用过两者的人都会同意 GetStorage 更易于使用。

为了清理我的示例,我删除了完成您所要求的内容所不需要的任何内容。根据应用其余部分的情况,您可能不需要恢复我删除的大部分或全部变量。

首先,让我们将逻辑和变量移动到 GetX class,以便可以从应用程序的任何位置访问它们。它还有助于清理您的 UI 代码。

class RatingController extends GetxController {
  int currentRating = 0;
  final box = GetStorage();

  @override
  void onInit() { // called whenever we initialize the controller
    super.onInit();
    currentRating = box.read('rating') ?? 0; // initializing current rating from storage or 0 if storage is null
  }

  void updateAndStoreRating(int rating) {
    currentRating = rating;
    box.write('rating', rating); // stores to local database
    update(); // triggers a rebuild of the GetBuilder Widget
  }

  Widget buildRatingStar(int index) {
    if (index < currentRating) {
      return Icon(
        Icons.star,
        color: Colors.yellow,
      );
    } else {
      return Icon(
        Icons.star,
        color: Colors.white,
      );
    }
  }
}

我在此页面上添加了一个按钮只是为了演示目的。由于此演示包括路由,我使用 Getx 也是一种更容易进行路由的方法,但它与回答您的问题完全无关或没有必要。此页面现在也可以是无状态的。

class Ratingpage extends StatelessWidget {
  static const id = 'rating_page'; // see GetMaterialApp for this usage

  final controller = Get.find<RatingController>(); // finding the same instance of initialized controller

  Widget _buildBody() {
    final stars = List<Widget>.generate(5, (index) {
      return GetBuilder<RatingController>( // rebuilds when update() is called from GetX class
        builder: (controller) => Expanded(
          child: GestureDetector(
            child: controller.buildRatingStar(index),
            onTap: () {
              controller.updateAndStoreRating(index + 1); // +1 because index starts at 0 otherwise the star rating is offset by one
            },
          ),
        ),
      );
    });
    return Row(
      children: [
        Expanded(
          child: Row(
            children: stars,
          ),
        ),
        Expanded(
          child: TextButton(
            onPressed: () {
              controller.updateAndStoreRating(0);
            },
            child: Text(
              "Clear",
              style: TextStyle(color: Colors.white),
            ),
          ),
        ),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        _buildBody(),
        ElevatedButton(
          onPressed: () {
            Get.to(() => OtherPage()); // equivalent of Navigator.push....
          },
          child: Text('Other Page'),
        )
      ],
    );
  }
}

您的主要方法现在看起来像这样,因为我们需要初始化控制器和存储。

void main() async {
  await GetStorage.init();
  Get.put(RatingController());

  runApp(MyApp());
}

再说一遍,只是为了方便路由,我们使用 GetMaterialApp 并在那里定义页面。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'Material App',
      home: Ratingpage(),
      getPages: [ // only necessary for routing, not for storage or state management
        GetPage(name: OtherPage.id, page: () => OtherPage()),
        GetPage(name: Ratingpage.id, page: () => Ratingpage()),
      ],
    );
  }
}

编辑:添加 SharedPreferences 由于未维护的包与 GetStorage 路径提供程序依赖性冲突。

SharedPreferences prefs; 添加到您的 GetX class。

现在这是您的更新功能。

void updateAndStoreRating(int rating) {
    currentRating = rating;
    prefs.setInt('rating', rating); //SharedPreferences way
    update(); // triggers a rebuild of the GetBuilder Widget
  }

在 GetX 控制器中添加一个初始化函数 class。

 Future<void> initSp() async {
    prefs = await SharedPreferences.getInstance();
    currentRating = prefs.getInt('rating') ?? 0;
  }

现在你的 main 有点不一样了。

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  final controller = Get.put(RatingController());
  await controller.initSp();

  runApp(MyApp());
}