【问题标题】:Consumer not rebuilding UI using riverpod消费者不使用 Riverpod 重建 UI
【发布时间】:2021-04-21 23:12:12
【问题描述】:

我正在尝试使用 Riverpod 制作简单的 stateNotifier。当我单击按钮时,它将在值之间切换。我检查了值,按下按钮时它会改变。问题是 UI 没有自行重建。我检查了文档并且很确定我做得对。

主屏幕

class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {

  @override
  void initState() {
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Consumer(
        builder: (context, watch, child) {
          final drawer = watch(drawerProvider.state);
          return Container(
            width: MediaQuery.of(context).size.width,
            child: Column(
              children: [
                Text(drawer.isOpen.toString()),
                Text(drawer.x.toString()),
                Text(drawer.y.toString()),
                Text(drawer.scale.toString()),
                FloatingActionButton(
                  onPressed: (){
                    context.read(drawerProvider).toggleDrawer();
                  }
                )
              ],
            ),
          );
        },
      ),
    );
  }
}

提供者

import 'package:flutter_riverpod/all.dart';

class Drawer{
  double x,y,scale;
  bool isOpen;
  Drawer(this.x,this.y,this.scale,this.isOpen);
}

class DrawerNotifier extends StateNotifier<Drawer>{
  DrawerNotifier() : super(Drawer(0,0,1,false));
  void toggleDrawer(){
    if(state.isOpen){
      state.x = 0;
      state.y = 0;
      state.scale = 1;
    }else{
      state.x = 0.5;
      state.y = 0.1;
      state.scale = 0.8;
    }
    state.isOpen = !state.isOpen;
  }
}

final drawerProvider = StateNotifierProvider((ref) => new DrawerNotifier());

【问题讨论】:

    标签: flutter dart provider flutter-provider riverpod


    【解决方案1】:
        import 'package:flutter/material.dart';
    import 'package:flutter_riverpod/flutter_riverpod.dart';
    
    @immutable
    class Drawer {
      final double x;
      final double y;
      final double scale;
      final bool isOpen;
    
      Drawer(this.x, this.y, this.scale, this.isOpen);
    
      factory Drawer.initial() {
        return Drawer(0, 0, 1, false);
      }
      Drawer copyWith({
        double x,
        double y,
        double scale,
        bool isOpen,
      }) {
        return Drawer(
          x ?? this.x,
          y ?? this.y,
          scale ?? this.scale,
          isOpen ?? this.isOpen,
        );
      }
    
      @override
      String toString() {
        return 'Drawer(x: $x, y: $y, scale: $scale, isOpen: $isOpen)';
      }
    }
    
    class DrawerNotifier extends StateNotifier<Drawer> {
      final Drawer drawer;
      DrawerNotifier(this.drawer) : super(drawer ?? Drawer.initial());
    
      void toggleDrawer() {
        if (state.isOpen) {
          state = state.copyWith(x: 0, y: 0, scale: 1);
        } else {
          state = state.copyWith(x: 0.5, y: 0.1, scale: 0.8);
        }
        state = state.copyWith(isOpen: !state.isOpen);
        print("new state>> $state");
      }
    }
    
    final drawerProvider =
        StateNotifierProvider((ref) => new DrawerNotifier(Drawer.initial()));
    
    class DrawerScreen extends StatefulWidget {
      @override
      _DrawerScreenState createState() => _DrawerScreenState();
    }
    
    class _DrawerScreenState extends State<DrawerScreen> {
      @override
      void initState() {
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return SafeArea(
          child: Consumer(
            builder: (context, watch, child) {
              final drawer = watch(drawerProvider.state);
              return Container(
                width: MediaQuery.of(context).size.width,
                child: Column(
                  children: [
                    Text(drawer.isOpen.toString()),
                    Text(drawer.x.toString()),
                    Text(drawer.y.toString()),
                    Text(drawer.scale.toString()),
                    FloatingActionButton(onPressed: () {
                      context.read(drawerProvider).toggleDrawer();
                    })
                  ],
                ),
              );
            },
          ),
        );
      }
    }
    

    【讨论】:

    • 我已经尝试将代码从 ChangeNotifier() 更改为 StateNotifier() 1 周。我有类似的问题,但用“copyWith()”方法解决了这个问题。谢谢!作为旁注,我不是专业的颤振开发人员,不要评判我:)
    • 这是一个体面且正确的答案,但它没有明确说明修复工作的方式或原因。关键是你替换状态对象,而不是简单地更新它的属性......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-24
    • 1970-01-01
    • 2021-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-18
    相关资源
    最近更新 更多