2

我正在尝试从 UI 外部更新我的 Provider 内部的值,如文档中所述:

final container = riverpod.ProviderContainer();
AppProvider _appProvider = container.read(appProvider);
_appProvider.setMode(true);

在我的 setMode 方法中,我调用 notifyListeners()。现在的问题是我的小部件没有重建,即使我的提供程序中的值成功更改并通知了它的侦听器。小部件是这样听的:

riverpod.Consumer(builder: (context, watch, child) {
    AppProvider _appProvider = watch(appProvider);
...

从UI内部更新提供程序时,小部件将按预期重建。

在这种情况下,我还需要做什么才能正确重建 UI?

4

1 回答 1

1

在这种情况下,文档有些误导。确实,您可以在Provider没有上下文的情况下以这种方式访问​​ a ,但您也在实例化一个 new ProviderContainer,它是存储所有提供程序状态的位置。通过这样做,您正在创建然后修改一个新的Notifier; 这意味着Notifier您的小部件正在收听的内容保持不变。

您可以在小部件树之外使用提供程序的一种方法是ProviderContainerProviderScope. 小心这一点,因为它可能会导致意想不到的后果。

用这个替换你的main.dart代码:

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

//Provider container which holds the state of all my providers
//This would normally be inaccessible inside of the ProviderScope
final providerContainer = ProviderContainer();

//A function that accesses and uses myNotifierProvider ***Without needing a context***
void incrementCountWithoutContext() {
  var provider = providerContainer.read(myNotifierProvider);
  provider.incrementCount();
}

final myNotifierProvider = ChangeNotifierProvider((_) {
  return MyNotifier();
});

class MyNotifier extends ChangeNotifier {
  int count = 0;

  void incrementCount() {
    count++;
    notifyListeners();
  }
}

void main() {
  runApp(
    //Here is where we pass in the providerContainer declared above
    UncontrolledProviderScope(
      container: providerContainer,
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends ConsumerWidget {
  @override
  Widget build(BuildContext context, ScopedReader watch) {
    final _provider = watch(myNotifierProvider);

    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('You have pushed the button this many times:'),
            Text(
              '${_provider.count}',
              style: Theme.of(context).textTheme.headline4,
            ),
            ElevatedButton(
              //Increment count by accessing the provider the usual way
              onPressed: _provider.incrementCount,
              child: Text('Increment count the usual way'),
            ),
            ElevatedButton(
              //Increment the count using our global function
              //Notice no context is passed to this method
              onPressed: incrementCountWithoutContext,
              child: Text('Increment count without context'),
            )
          ],
        ),
      ),
    );
  }
}
于 2021-01-31T01:37:56.033 回答