【问题标题】:Flutter/Riverpod: UI not updating on state change within a StateNotifierProviderFlutter/Riverpod:UI 不更新 StateNotifierProvider 中的状态更改
【发布时间】:2021-04-05 10:23:47
【问题描述】:

当我知道状态正在改变的事实时,我的应用程序的 UI 没有更新。我正在使用 Riverpod 的 watch 方法来处理此问题,但除非我进行热重载,否则更改不会生效。

我有一个班级HabitListStateNotifier,其中包含从列表中添加/删除习惯的方法:

class HabitListStateNotifier extends StateNotifier<List<Habit>> {
  HabitListStateNotifier(state) : super(state ?? []);

  void startAddNewHabit(BuildContext context) {
    showModalBottomSheet(
        context: context,
        builder: (_) {
          return NewHabit();
        });
  }

  void addNewHabit(String title) {
    final newHabit = Habit(title: title);
    state.add(newHabit);
  }

  void deleteHabit(String id) {
    state.removeWhere((habit) => habit.id == id);
  }
}

这里是提供者:

final habitsProvider = StateNotifierProvider(
  (ref) => HabitListStateNotifier(
    [
      Habit(title: 'Example Habit'),
    ],
  ),
);

以下是HabitList(UI 部分未更新)的实现方式:

class HabitList extends ConsumerWidget {
  @override
  Widget build(BuildContext context, ScopedReader watch) {
    final habitList = watch(habitsProvider.state);

    /////////////not updating/////////////
    return ListView.builder(
      shrinkWrap: true,
      scrollDirection: Axis.vertical,
      itemBuilder: (context, index) {
        return HabitCard(
          habit: habitList[index],
        );
      },
      itemCount: habitList.length,
    );
    /////////////not updating/////////////
  }
}

最后,HabitCardHabitList 的组成部分):

class HabitCard extends StatelessWidget {
  final Habit habit;

  HabitCard({@required this.habit});

  @override
  Widget build(BuildContext context) {

    /////////////function in question/////////////
    void deleteHabit() {
      context.read(habitsProvider).deleteHabit(habit.id);
    }
    /////////////function in question/////////////

    return Card(
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(devHeight * 0.03),
      ),
      color: Colors.grey[350],
      elevation: 3,
      child: Column(
        children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              HabitTitle(
                title: habit.title,
              ),
              Consumer(
                builder: (context, watch, child) => IconButton(
                  padding: EdgeInsets.all(8),
                  icon: Icon(Icons.delete),

                  /////////////function in question/////////////
                  onPressed: deleteHabit,
                  /////////////function in question/////////////
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

当我按下 HabitCard 中的删除图标时,我知道 Habit 正在从列表中删除,但更改并未反映在 UI 中。但是,当我进行热重载时,它会按预期消失。我在这里做错了什么?

【问题讨论】:

  • 就像您在评论中已经弄清楚一样,您需要更新状态以强制刷新,在您的情况下,因为您只是在列表中添加/删除一个新对象,它将不会' t 刷新,除非你这样做 state = state.add(newHabit);这也发生在 ValueNotifier 上,因为它被修改的是同一个对象,而不是一个新对象

标签: flutter dart flutter-provider riverpod


【解决方案1】:

我不知道这是否是正确的处理方式,但我想通了。在HabitListStateNotifier 中,对于addNewHabitdeleteHabit,我在末尾添加了这行代码:state = state;,它完全按照我想要的方式工作。

【讨论】:

    【解决方案2】:

    我曾经通过将state = state; 放在末尾来解决此问题,但现在由于某种原因可能会出现抖动或 Riverpod 更新,它不再起作用了。

    无论如何,这就是我现在设法解决的方法。

      void addNewHabit(String title) {
        List<Habit> _habits = [...state]; 
        final newHabit = Habit(title: title);
        _habits.add(newHabit);
        state = _habits ; 
      }
    

    我理解的解释。当 state 等于一个对象时,为了触发消费者重建。 state 必须等于该对象的新值,但更新 state 对象本身的变量将不起作用。

    希望这对任何人都有帮助。

    【讨论】:

      【解决方案3】:

      你需要像这样写你的add & delete

      void addNewHabit(String title) {
          state = [ ...state, Habit(title: title)];
      }
      
      void deleteHabit(String id) {
        state = state.where((Habit habit) => habit.id != id).toList();
      }
      

      您需要将旧列表换成新列表,Riverpod 才能启动。

      【讨论】:

      • 从 Provider 迁移后,我真的开始对 Riverpod 感到困惑。太感谢了。我看到,由于状态是不可变的,它必须用新数据替换自己,而不是在它是 List 时附加到它。
      猜你喜欢
      • 1970-01-01
      • 2021-03-24
      • 2023-04-09
      • 2018-10-16
      • 2021-12-09
      • 2020-10-10
      • 2020-09-03
      • 2022-12-18
      • 2016-10-02
      相关资源
      最近更新 更多