简体   繁体   English

对flutter_bloc的全局依赖

[英]Global dependency on flutter_bloc

I have a problem implementing an app on Flutter using flutter_bloc .我在使用flutter_bloc在 Flutter 上实现应用程序时遇到问题。 I understood the core concepts but I found an "edge case" where there is not examples or guides (at least that I could find):我理解了核心概念,但我发现了一个没有示例或指南的“边缘案例”(至少我能找到):

(I will simplify the problem) I have a bloc called AuthBloc that manages the App . (我将简化问题)我有一个名为AuthBloc的集团来管理App If the state is NotAuthenticated then the App should show the LoginScreen but if is Authenticated the App should show the HomeScreen .如果 state 是NotAuthenticated则应用程序应该显示LoginScreen但如果是Authenticated应用程序应该显示HomeScreen Inside the HomeScreen I have 4 blocs, where each bloc has its states and events, but all of them has dependencies on different Repositories to get some data from an API.HomeScreen内,我有 4 个块,其中每个块都有其状态和事件,但它们都依赖于不同的Repositories以从 API 获取一些数据。

All the Repositories need a token to make the API requests.所有Repositories都需要一个令牌来发出 API 请求。 The first problem came here.第一个问题来了。 How can I get the token from all the repositories?如何从所有存储库中获取令牌? If I use a UserRepository to store the token, I will need to pass it as dependency to each Repository (probably works but I don't think its the right way to do it).如果我使用UserRepository来存储令牌,我需要将它作为依赖项传递给每个存储库(可能有效,但我认为这不是正确的方法)。 So, what can be the right way to manage this?那么,管理这个问题的正确方法是什么?

The second problem is:第二个问题是:

If somehow I can get the token on all the repositories queries, what happens when the token is revoked?如果我能以某种方式在所有存储库查询中获得令牌,那么当令牌被撤销时会发生什么? The app should return to the LoginScreen and for that I would need to notify the AuthBloc through an event (for example InvalidTokenEvent ).该应用程序应返回到LoginScreen ,为此我需要通过事件(例如InvalidTokenEvent )通知AuthBloc And the AuthBloc should change its state to NotAuthenticated and that will rebuild the LoginScreen .并且AuthBloc应该将其 state 更改为NotAuthenticated ,这将重建LoginScreen But the question is: How can I notify the AuthBloc from other blocs or repositories?但问题是:如何从其他集团或存储库通知AuthBloc The first idea I had is through dependency injection: I can pass the AuthBloc to every other bloc in the constructor, so when the repository request returns a token expired, the XBloc can call AuthBloc.add(InvalidTokenEvent) .我的第一个想法是通过依赖注入:我可以将 AuthBloc 传递给构造函数中的每个其他块,因此当存储库请求返回令牌过期时, XBloc可以调用AuthBloc.add(InvalidTokenEvent) But again, if I have a lot of blocs I would need to do that in each bloc.但同样,如果我有很多集团,我需要在每个集团中都这样做。 So, what's the right way to do this?那么,这样做的正确方法是什么?

Thank you for any help!感谢您的任何帮助!

All the Repositories need a token to make the API requests.所有存储库都需要一个令牌来发出 API 请求。 The first problem came here.第一个问题来了。 How can I get the token from all the repositories?如何从所有存储库中获取令牌? If I use a UserRepository to store the token, I will need to pass it as dependency to each Repository (probably works but I don't think its the right way to do it).如果我使用 UserRepository 来存储令牌,我需要将它作为依赖项传递给每个存储库(可能有效,但我认为这不是正确的方法)。 So, what can be the right way to manage this?那么,管理这个问题的正确方法是什么?

This is not a bad practice to apply (adding it as dependency), but to make it easier, you can use getIt and injectable libraries to have a proper dependency injection solution.这不是一个不好的做法(将其添加为依赖项),但为了使其更容易,您可以使用 getIt 和可注入库来获得适当的依赖项注入解决方案。

Another way is, adding an interceptor to your networking layer, which is, before making a http request you can intercept your request, add token to your request in that layer and proceed to requesting phase.另一种方法是,在您的网络层添加一个拦截器,也就是说,在发出 http 请求之前,您可以拦截您的请求,在该层的请求中添加令牌并继续请求阶段。

Most of the networking libraries has request and response interceptors like below:大多数网络库都有请求和响应拦截器,如下所示:

But this is not an issue of Bloc library.但这不是 Bloc 库的问题。

If somehow I can get the token on all the repositories queries, what happens when the token is revoked?如果我能以某种方式在所有存储库查询中获得令牌,那么当令牌被撤销时会发生什么?

You can add another response interceptor to detect if you have unauthenticated response so you can logout user.您可以添加另一个响应拦截器来检测您是否有未经身份验证的响应,以便您可以注销用户。

Using getIt , you can gether that bloc from your global dependency container and logout user.使用getIt ,您可以从全局依赖容器和注销用户中收集该块。

To answer your first problem:要回答您的第一个问题:

Your repositories should not be handling the API authentication.您的存储库不应处理 API 身份验证。 That should be the job of the data layer under the repository layer.这应该是存储库层下数据层的工作。

What I recommend is having one instance of a http client and then provide this instance to all the repositories.我建议拥有一个 http 客户端实例,然后将此实例提供给所有存储库。 This way your client can have an interceptor that handles adding the saved token to all your requests.这样,您的客户端可以有一个拦截器来处理将保存的令牌添加到您的所有请求。 So your repositories could look something like this:因此,您的存储库可能如下所示:

class OrderRepository {
  const OrderRepository(this.httpClient);

  final HttpClient httpClient;
}

Then the rest would be as simple as initializing your httpclient then pass it to your repositories which you can provide to your app and blocs by using RepositoryProvider or MultiRepositoryProvider .然后 rest 将像初始化您的 httpclient 然后将其传递到您的存储库一样简单,您可以使用RepositoryProviderMultiRepositoryProvider将其提供给您的应用程序和块。 Then do the same thing with your repositories and blocs passing your repositories to your blocs inside of your blocproviders.然后对您的存储库和 bloc 执行相同的操作,将您的存储库传递给 blocproviders 内的 bloc。

To answer your second problem:要回答您的第二个问题:

If authenticating and passing your token to all requests can be handled at the http client layer so should unauthenticating and revoking the token.如果可以在 http 客户端层处理身份验证并将令牌传递给所有请求,那么应该取消身份验证和撤销令牌。 Therefore to reflect this in your authentication state your AuthRepository should listen to your http client and similarly your AuthBloc should listen to your AuthRepository.因此,要在您的身份验证 state 中反映这一点,您的 AuthRepository 应该听您的 http 客户端,同样您的 AuthBloc 应该听您的 AuthRepository。 You can do this by exposing a stream of your authentication status in both your http client and your AuthRepository that gets listened to in your auth bloc.您可以通过在您的 http 客户端和您的 AuthRepository 中公开您的身份验证状态的 stream 来做到这一点,该 AuthRepository 会在您的 auth bloc 中被监听。

So it would look like this: http client gets a 401 error so it removes the token from storage and then adds the unauthenticated status to the stream.所以它看起来像这样:http 客户端收到 401 错误,因此它从存储中删除令牌,然后将未经身份验证的状态添加到 stream。 This stream is then exposed in auth repository and then in auth bloc have a stream subscription which listens to the authentication status to emit an unauthenticated state.然后,此 stream 在 auth 存储库中公开,然后在 auth bloc 中有一个 stream 订阅,该订阅侦听身份验证状态以发出未经身份验证的 Z9ED39E2EA931586B6A985A6942EF7。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM