【问题标题】:Flutter - Riverpod 2.0 - .select() function is not preventing unnecessary rebuilds at all, .select() is not workingFlutter - Riverpod 2.0 - .select() 函数根本无法阻止不必要的重建,.select() 不起作用
【发布时间】:2023-02-07 20:15:54
【问题描述】:

我正在使用带有选择的状态通知程序和状态通知程序提供程序来仅将重建应用于对象中的特定字段。但无论我选择与否,整个小部件都会重建。

我有以下示例代码来简化我的问题:

final counterProvider =
    StateNotifierProvider<CounterState, Counter>((ref) => CounterState());

class Counter {
  int count1;
  int count2;

  Counter(this.count1, this.count2);
}

class CounterState extends StateNotifier<Counter> {
  CounterState() : super(Counter(0, 0));

  void inc1() => state = Counter(state.count1 + 1, state.count2);

  void inc2() => state = Counter(state.count1, state.count2 + 1);
}

和以下消费者小部件:

class TestWidget extends ConsumerWidget {

  const TestWidget({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) => Scaffold(
      body: Column(
        children: [
      Text(ref.watch(counterProvider.select((value) {
        print("rebuilt counter 1 Text with val: ${value.count1}");
        return value.count1.toString();
      }))),
      Text(ref.watch(counterProvider.select((value) {
        print("rebuilt Counter 2 Text with val: ${value.count2}");
        return value.count2.toString();
      }))),
      ElevatedButton(
          onPressed: () => ref.read(counterProvider.notifier).inc1(),
          child: const Text("Inc 1")),
      ElevatedButton(
          onPressed: () => ref.read(counterProvider.notifier).inc2(),
          child: const Text("Inc 2"))
        ],
      ));
}

我很期待按inc1() 按钮不重建第二个文本。只有第一个。

但是当我按 3 次 inc1 时控制台中的输出如下:

I/flutter (19394): rebuilt counter 1 Text with val: 0
I/flutter (19394): rebuilt Counter 2 Text with val: 0
D/EGL_emulation(19394): app_time_stats: avg=417.64ms min=8.70ms max=4924.00ms count=13
I/flutter (19394): rebuilt counter 1 Text with val: 1
I/flutter (19394): rebuilt Counter 2 Text with val: 0
I/flutter (19394): rebuilt counter 1 Text with val: 1
I/flutter (19394): rebuilt Counter 2 Text with val: 0
D/EGL_emulation(19394): app_time_stats: avg=78.42ms min=2.63ms max=1171.43ms count=18
I/flutter (19394): rebuilt counter 1 Text with val: 2
I/flutter (19394): rebuilt Counter 2 Text with val: 0
I/flutter (19394): rebuilt counter 1 Text with val: 2
I/flutter (19394): rebuilt Counter 2 Text with val: 0
D/EGL_emulation(19394): app_time_stats: avg=34.74ms min=2.47ms max=721.10ms count=25
I/flutter (19394): rebuilt counter 1 Text with val: 3
I/flutter (19394): rebuilt Counter 2 Text with val: 0
I/flutter (19394): rebuilt counter 1 Text with val: 3
I/flutter (19394): rebuilt Counter 2 Text with val: 0

我期待在控制台中:

I/flutter (19394): rebuilt counter 1 Text with val: 0
I/flutter (19394): rebuilt Counter 2 Text with val: 0
D/EGL_emulation(19394): app_time_stats: avg=417.64ms min=8.70ms max=4924.00ms count=13
I/flutter (19394): rebuilt counter 1 Text with val: 1
D/EGL_emulation(19394): app_time_stats: avg=78.42ms min=2.63ms max=1171.43ms count=18
I/flutter (19394): rebuilt counter 1 Text with val: 2
D/EGL_emulation(19394): app_time_stats: avg=34.74ms min=2.47ms max=721.10ms count=25
I/flutter (19394): rebuilt counter 1 Text with val: 3

那么我对select()函数有什么理解不正确? 以及为什么第一个文本虽然发生了一次更改却重建了两次?

【问题讨论】:

  • 你想分离状态,就像这里的状态包含两个计数值Counter,要更新状态,你需要分配新的实例。
  • 究竟在哪里分配一个新实例?如果你指的是inc1()函数,我已经分配了一个新实例。如果还有哪里那么你能告诉我你的意思到底是哪里吗?
  • 我的意思是一旦你 `state = Counter..` 它就创建了新的实例并且两个值都变成了新的对象
  • 是的,这是正确的。我正在尝试遵循不可变状态管理的原则。你是说我不能用不可变的状态管理来执行我想做的事情吗?

标签: flutter riverpod


【解决方案1】:

select 函数与描述的问题无关。

select 用于跳过一些您不关心的更新。在您关心更新的同时,希望重建更少的 widgets。

为此,解决方案是:

  • 将您的个人文本提取为单独的ConnsumerWidget
  • 将您的文本包装成Consumer

喜欢:

Column(
  children: [
    Consumer(builder: (context, ref, _) {
      return Text(ref.watch(fooProvider));
    }),
    Consumer(builder: (context, ref, _) {
      return Text(ref.watch(barProvider));
    }),
  ],
)

这样,fooProvider 的更新将不会重建监听barProvider 的文本

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-01
    • 2013-11-18
    • 2015-05-06
    • 2018-12-15
    • 1970-01-01
    • 2016-02-26
    • 2017-12-17
    • 2016-07-06
    相关资源
    最近更新 更多