消费者不使用 Riverpod 重建 UI

Posted

技术标签:

【中文标题】消费者不使用 Riverpod 重建 UI【英文标题】:Consumer not rebuilding UI using riverpod 【发布时间】: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());

【问题讨论】:

【参考方案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()”方法解决了这个问题。谢谢!作为旁注,我不是专业的颤振开发人员,不要评判我:) 这是一个体面且正确的答案,但它没有明确说明修复工作的方式或原因。关键是你替换状态对象,而不是简单地更新它的属性......

以上是关于消费者不使用 Riverpod 重建 UI的主要内容,如果未能解决你的问题,请参考以下文章

加载数据时如何等待或重建消费者

当消费者触发重建时,MaterialApp 主页小部件不会被渲染。需要油漆

3D重建算法原理

使用 Swagger UI 和 Swashbuckle 按消费者过滤 API 端点

kafka集群里面如何重建单个节点

Riverpod 错误:未定义的类“ScopedReader”