如何在 Flutter 中使用另一个提供者内部的提供者

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

我想创建一个具有

authentication service
的应用程序,根据用户角色具有不同的权限和功能(例如消息)。

因此,我创建了一个用于用户和登录管理的

Provider
,另一个用于用户可以看到的消息。

现在,我想在用户登录时获取消息(一次)。在

Widgets
中,我可以通过
Provider.of<T>(context)
访问提供程序,我想这是一种
Singleton
。但是我如何从另一个类(在本例中是另一个提供者)访问它?

flutter dart flutter-layout
6个回答
35
投票

感谢您的回答。与此同时,我用另一种解决方案解决了这个问题:

main.dart
文件中,我现在使用
ChangeNotifierProxyProvider
而不是
ChangeNotifierProvider
来表示依赖的提供程序:

// main.dart
return MultiProvider(
      providers: [
        ChangeNotifierProvider(builder: (_) => Auth()),
        ChangeNotifierProxyProvider<Auth, Messages>(
          builder: (context, auth, previousMessages) => Messages(auth),
          initialBuilder: (BuildContext context) => Messages(null),
        ),
      ],
      child: MaterialApp(
        ...
      ),
    );

现在,当登录状态更改并通过身份验证提供程序时,将重建消息提供程序:

class Messages extends ChangeNotifier {
    final Auth _authProvider;

    List<Message> _messages = [];
    List<Message> get messages => _messages;

    Messages(this._authProvider) {
        if (this._authProvider != null) {
            if (_authProvider.loggedIn) fetchMessages();
        }
    }

    ...
}

31
投票

version >=4.0.0 开始,我们需要采取与 @updatestage 的回答稍有不同的做法。

return MultiProvider(
  providers: [
    ChangeNotifierProvider(builder: (_) => Auth()),
    ChangeNotifierProxyProvider<Auth, Messages>(
      update: (context, auth, previousMessages) => Messages(auth),
      create: (BuildContext context) => Messages(null),
    ),
  ],
  child: MaterialApp(
    ...
  ),
);

15
投票

在 ChangeNotifierProxyProvider 的构造函数中传递另一个提供程序可能会导致您丢失状态,在这种情况下您应该尝试以下操作。

ChangeNotifierProxyProvider<MyModel, MyChangeNotifier>(
  create: (_) => MyChangeNotifier(),
  update: (_, myModel, myNotifier) => myNotifier
    ..update(myModel),
);
class MyChangeNotifier with ChangeNotifier {
  MyModel _myModel;

  void update(MyModel myModel) {
    _myModel = myModel;
  }
}

3
投票

很简单:第一个Provider提供一个类的实例,例如:

LoginManager
。另一个提供
MessageFetcher
。在
MessageFetcher
中,无论您有什么方法,只需向其添加
Context
参数并通过提供新的上下文来调用它即可。

也许你的代码看起来像这样:

MessageFetcher messageFetcher = Provider.of<ValueNotifier<MessageFetcher>>(context).value;
String message = await messageFetcher.fetchMessage(context);

MessageFetcher
你可以拥有:

class MessageFetcher {
  Future<String> fetchMessage(BuildContext context) {
    LoginManager loginManager = Provider.of<ValueNotifier<LoginManager>>(context).value;
    loginManager.ensureLoggedIn();
    ///...
  }
}

-1
投票

使用 Riverpod 似乎会容易得多,尤其是将参数传递到

.family
构建器以使用提供程序类作为许多不同版本的千篇一律的想法。


-1
投票

为什么不直接将上下文传递给提供者的构造函数,并在提供者内部使用该上下文,如下所示???

///in your main provider config...
 MultiProvider(
  providers: [
    ChangeNotifierProvider(
      create: (context) => MyProvider(context),
    ),
    ChangeNotifierProvider(
      create: (_) => MyProviderB(),
    ),
  ],

///in your provider...
  class MyProvider with ChangeNotifier {
    BuildContext context;
    
    MyProvider(this.context);

    myFunction(){
      var data = this.context.read<MyProviderB>().data;
///some more code here...
    }
  }
© www.soinside.com 2019 - 2024. All rights reserved.