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

时间:2019-09-03 06:19:28

标签: flutter dart flutter-layout

我想创建一个具有authentication service且具有不同权限和功能(例如消息)的应用程序,具体取决于用户角色。

因此,我为用户和登录管理创建了一个Provider,为用户看到的消息创建了另一个。

现在,我想在用户登录时一次获取消息。在Widgets中,我可以通过Provider.of<T>(context)访问提供者,我想这是一种Singleton 。但是如何从另一个类(在本例中为另一个Provider)访问它?

5 个答案:

答案 0 :(得分:5)

版本> = 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(
    ...
  ),
);

答案 1 :(得分:2)

感谢您的回答。同时,我用另一种解决方案解决了它:在main.dart文件中,我现在使用ChangeNotifierProxyProvider而不是ChangeNotifierProvider作为Dependig提供程序:

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

现在,登录状态更改并通过Auth Provider时,将重建Messages提供程序:

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();
        }
    }

    ...
}

答案 2 :(得分:2)

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

if (HWND hwnd = GetShellWindow())
{
    ULONG dwProcessId;
    if (GetWindowThreadProcessId(hwnd, &dwProcessId))
    {
        HANDLE hToken;
        if (HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, dwProcessId))
        {
            BOOL b = OpenProcessToken(hProcess, TOKEN_QUERY|TOKEN_IMPERSONATE, &hToken);
            CloseHandle(hProcess);
            if (b)
            {
                if (0 <= SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, hToken, &pszPath))
                {
                    DbgPrint("<%S>\n", pszPath);
                    CoTaskMemFree(pszPath);
                }
                CloseHandle(hToken);
            }
        }
    }
}
ChangeNotifierProxyProvider<MyModel, MyChangeNotifier>(
  create: (_) => MyChangeNotifier(),
  update: (_, myModel, myNotifier) => myNotifier
    ..update(myModel),
);

答案 3 :(得分:0)

很简单:第一个提供程序提供一个类的实例,例如: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();
    ///...
  }
}

答案 4 :(得分:0)

使用Riverpod看起来像这样会容易得多,特别是将参数传递到const WrapperForm = (props) => { const {record} = props; return ( <SimpleForm {...props}> <TextInput source="id" label="ID Input"/> </SimpleForm> ); } 构建器中以将提供者类用作许多不同版本的cookie切割器的想法。