【问题标题】:flutter riverpod ConsumerWidget not being rebuilt颤动的riverpod ConsumerWidget没有被重建
【发布时间】:2021-03-27 21:08:59
【问题描述】:

我刚刚将riverpod 实现到我编写的一个小应用程序中。

flutter_riverpod: ^0.12.1

我的问题是,当我更新提供程序时,尽管调用了“watch”,但小部件并未重建。

提供程序实质上跟踪应显示的当前页面。

import 'dart:developer';

import 'package:flutter_riverpod/flutter_riverpod.dart';

final currentPageProvider = StateNotifierProvider((ref) => CurrentPage());

class CurrentPage extends StateNotifier<int> {
  CurrentPage() : super(-1);

  set currentPage(int page) {
    log('currentPage set to $page');
    state = page;
  }

  int get currentPage => state;
}

PageButtons 小部件绘制一组 RaisedButtons。当用户单击其中一个凸起的按钮时,当前页面编号。应该更改并且应该重建 PageButton 小部件,以便我们可以更改与当前页面对应的 RaisedButton 的颜色。

import 'dart:developer';
import 'dart:math' hide log;

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fsm2/fsm2.dart' hide State;
import 'package:fsm2_viewer/src/providers/current_page.dart';
import 'package:fsm2_viewer/src/providers/log_provider.dart';

class PageButtons extends ConsumerWidget {
  final List<SvgFile> pages;
  PageButtons(this.pages);

  @override
  Widget build(BuildContext context, ScopedReader watch) {
    /// watch the currentPageProvider so we are rebuilt when the page
    /// no changes.
    int currentPage = watch(currentPageProvider).currentPage;
    log('building PageButons currentPage: $currentPage');
    if (pages.length == 0) {
      return Container(width: 0, height: 0);
    }

    currentPage = min(currentPage, pages.length - 1);

    var buttons = <Widget>[];
    for (var pageNo = 0; pageNo < pages.length; pageNo++) {
      buttons.add(Padding(
          padding: EdgeInsets.only(right: 5, left: 5),
          child: RaisedButton(
              color: (pageNo == currentPage ? Colors.blue : Colors.grey),
              onPressed: () {
                context.read(logProvider).log = 'onpressed';
                /// User click the page button so update the current page.
                context.read(currentPageProvider).currentPage = pageNo;
                context.read(logProvider).log = 'changed to page $pageNo';
              },
              child: Text('${pageNo + 1}'))));
    }
    return Row(children: buttons);
  }
}

在上面的build方法中可以看到我调用watch:

 int currentPage = watch(currentPageProvider).currentPage;

然后在 onPressed for a Raised 按钮中更新 currentPage:

              onPressed: () {
                /// User click the page button so update the current page.
                context.read(currentPageProvider).currentPage = pageNo;
                context.read(logProvider).log = 'onpressed';                
                context.read(logProvider).log = 'changed to page $pageNo';

在我的日志中我看到:

main:ALL> onpressed
main:ALL> currentPage set to 1
main:ALL> changed to page 1

日志告诉我正在调用 onPressed 方法,并且我正在更新 currentPageProvider。

但是没有调用 PageButtons 的构建器。

我做错了什么?

【问题讨论】:

  • “设置为 1”。那条线之前是什么?状态必须更改才能获得通知。
  • 这只是一种预感,但我不确定观察你的 getter 的值是否会产生与直接观察状态相同的行为。
  • @RandalSchwartz 它呈现多个按钮,我已经测试将其更改为不同的值。
  • @AlexHartford 如果我将行更改为使用状态,我会收到警告: int currentPage = watch(currentPageProvider).state;成员 'state' 只能在 'package:state_notifier/state_notifier.dart' 的子类的实例成员中使用。
  • @BrettSutton 你需要这样做:currentPage = watch(currentPageProvider.state);

标签: flutter dart provider riverpod


【解决方案1】:
    import 'dart:developer';
import 'dart:math' hide log;

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fsm2/fsm2.dart' hide State;
import 'package:fsm2_viewer/src/providers/current_page.dart';
import 'package:fsm2_viewer/src/providers/log_provider.dart';

class PageButtons extends ConsumerWidget {
  final List<SvgFile> pages;
  PageButtons(this.pages);

  @override
  Widget build(BuildContext context, ScopedReader watch) {
    /// watch the currentPageProvider so we are rebuilt when the page
    /// no changes.
    int currentPage = watch(currentPageProvider.state);
    log('building PageButons currentPage: $currentPage');
    if (pages.length == 0) {
      return Container(width: 0, height: 0);
    }

    currentPage = min(currentPage, pages.length - 1);

    var buttons = <Widget>[];
    for (var pageNo = 0; pageNo < pages.length; pageNo++) {
      buttons.add(Padding(
          padding: EdgeInsets.only(right: 5, left: 5),
          child: RaisedButton(
              color: (pageNo == currentPage ? Colors.blue : Colors.grey),
              onPressed: () {
                context.read(logProvider).log = 'onpressed';
                /// User click the page button so update the current page.
                context.read(currentPageProvider).currentPage = pageNo;
                context.read(logProvider).log = 'changed to page $pageNo';
              },
              child: Text('${pageNo + 1}'))));
    }
    return Row(children: buttons);
  }
}

【讨论】:

  • 请不要只发布代码作为答案,还要解释您的代码的作用以及它如何解决问题的问题。带有解释的答案通常更有帮助、质量更好,并且更有可能吸引投票
  • 他只是省略了状态关键字 int currentPage = watch(currentPageProvider.state); // 有了这个,你现在看到的是 stateNotifierProvider 的状态,而不是提供者本身
猜你喜欢
  • 2021-02-26
  • 2022-01-01
  • 2021-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-18
相关资源
最近更新 更多