使用嵌套监视方法的 RiverPod Provider 中出现意外的处置行为

问题描述 投票:0回答:1

我对 Riverpod 提供商有疑问。 当我们观察提供者中另一个提供者的状态和通知者时,它们可以被自动处置,即使它是非一次性提供者。

更详细: https://github.com/rrousselGit/riverpod/issues/3592

测试代码,可以在dartpad.dev上测试 请仅关注控制台输出和 UI 上的家庭控制器 ID。计数器不工作是正常的。

import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

void main() {
  runApp(
    ProviderScope(
      observers: [Logger()],
      child: const MyApp(),
    ),
  );
}

class Logger extends ProviderObserver {
  @override
  void didAddProvider(
    ProviderBase<dynamic> provider,
    Object? value,
    ProviderContainer container,
  ) {
    print('Added [${provider.name ?? provider.runtimeType}] value: $value');
  }

  @override
  void didDisposeProvider(
    ProviderBase<dynamic> provider,
    ProviderContainer container,
  ) {
    print('Disposed [${provider.name ?? provider.runtimeType}]');
  }
}

class HomeControllerState {
  HomeControllerState({required this.id});
  final int id;
}

class HomeController extends StateNotifier<HomeControllerState> {
  HomeController(this.ref)
      : super(HomeControllerState(id: Random().nextInt(1000)));
  late final StateNotifierProviderRef<HomeController, HomeControllerState> ref;

  @override
  HomeControllerState build() {
    return HomeControllerState(id: Random().nextInt(1000));
  }

  void watch() {
    ref.watch(testProvider);
  }

  void increment() {
    ref.watch(testProvider.notifier).increment();
  }
}

final homeControllerProvider =
    StateNotifierProvider<HomeController, HomeControllerState>((ref) {
  return HomeController(ref);
});

class TestState {
  TestState({this.count = 0});
  final int count;

  TestState copyWith({required int count}) {
    return TestState(count: count);
  }
}

class TestController extends Notifier<TestState> {
  @override
  TestState build() {
    return TestState();
  }

  void increment() {
    state = state.copyWith(count: state.count + 1);
  }
}

final testProvider =
    NotifierProvider<TestController, TestState>(TestController.new);

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        colorSchemeSeed: Colors.blue,
        useMaterial3: true,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends ConsumerWidget {
  const MyHomePage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final homeControllerState = ref.watch(homeControllerProvider);
    final homeController = ref.watch(homeControllerProvider.notifier);
    //final testState = ref.watch(testProvider);

    return Scaffold(
      appBar: AppBar(
        title: const Text('Riverpod Example with Nested Providers'),
      ),
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('HomeController ID: ${homeControllerState.id}'),
            const SizedBox(height: 20),
            const Text('TestController State:'),
            Text(
              '000',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
            ElevatedButton(
                onPressed: () {
                  homeController.watch();
                },
                child: Text('watch')),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => homeController.increment(),
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}
flutter dispose riverpod autodispose
1个回答
0
投票

现在我解决并理解了 这不是一个错误;而是一个错误。这是 Riverpod 的预期行为。

了解这一点非常重要:如果您在提供程序中调用

watch
并且监视的提供程序发生更改,则该提供程序也将被重新创建。

在这种情况下,我们应该使用

listen

我说得对吗?

© www.soinside.com 2019 - 2024. All rights reserved.