# Flutter/Riverpod – 是否可以从另一个StateNotifier()读取StateNotifier()的状态?

huangapple go评论77阅读模式
英文:

# Flutter/Riverpod - Is it possible to read() StateNotifier from another StateNotifier()

问题

I understand that you want a Chinese translation of the provided code snippets. Here they are:

我正在使用 Riverpod 作为状态管理器开发 Flutter 应用,目前我已经达到了需要实现错误处理的阶段。我的计划是在所有页面的基本小部件中实现错误处理提供程序,以便从状态通知器中获取:

```dart
class ErrorNotifier extends StateNotifier<ErrorModel>{
  ErrorNotifier() : super(ErrorModel(showError: false, exception: '', errorTitle: ''));

  void createException({
    required String exception,
    required String errorTitle
  }){
    state = state.update(showError: true, exception: exception, errorTitle: errorTitle);
  }

  void disbandError() {
    state = state.update(showError: false);
  }
}

class ErrorModel {
  bool showError;
  String exception;
  String errorTitle;

  ErrorModel({
    required this.showError,
    required this.exception,
    required this.errorTitle,
  });

  ErrorModel update({bool? showError, String? exception, String? errorTitle}) {
    return ErrorModel(
      showError: showError ?? this.showError,
      exception: exception ?? this.exception,
      errorTitle: errorTitle ?? this.errorTitle,
    );
  }
}

final errorProvider = StateNotifierProvider<ErrorNotifier, ErrorModel>(
        (ref) => ErrorNotifier(),
);

因此,每当 showError 改变为 true 时,我想从基本小部件中显示模态窗口,从而使错误处理对所有使用基本小部件的页面全局有效,但我需要通过其他状态通知器更改数据为错误模型。例如在这个状态通知器中:

class OnboardingNotifier extends StateNotifier<bool> {
  OnboardingNotifier() : super(SharedPreferencesService().getOnboarding());

  void getOnboarding() {
    state = SharedPreferencesService().getOnboarding();
    try {
      state = SharedPreferencesService().getOnboarding();
    } catch(e){
      ref.read(errorProvider.notifier).update(showError: true, exception: e, errorTitle: "发生错误");
    }
  }

  Future<void> setOnboarding(bool onboarding) async {
    try {
      await SharedPreferencesService().setOnboarding(onboarding);
    } catch(e){
      ref.read(errorProvider.notifier).update(showError: true, exception: e, errorTitle: "发生错误");
    }
  }
}

我希望在每个方法中添加 trycatch 块,并在捕获到错误时读取错误处理提供程序,并将 showError 值更改为 true,并且可以从基本小部件中监视到。我想象中的代码如下:

void getOnboarding() {
  state = SharedPreferencesService().getOnboarding();
  try {
    state = SharedPreferencesService().getOnboarding();
  } catch(e){
    ref.read(errorProvider.notifier).update(showError: true, exception: e, errorTitle: "发生错误");
  }
}

Future<void> setOnboarding(bool onboarding) async {
  try {
    await SharedPreferencesService().setOnboarding(onboarding);
  } catch(e){
    ref.read(errorProvider.notifier).update(showError: true, exception: e, errorTitle: "发生错误");
  }
}

我尝试寻找可能的解决方案,但找不到类似的问题,也没有在文档中找到相关信息。我需要在其他状态通知器中使用错误处理提供程序,而不仅仅是这个示例。如果有人做过类似的事情或者有更好的全局错误处理架构,我将非常高兴听到。


<details>
<summary>英文:</summary>

I am developing flutter app using Riverpod as state management and i reached a point where i want to implement Error handling. The way i plan it is due to having base widget for all the pages for that base widget to implement error handling provider from State Notofier:

class ErrorNotifier extends StateNotifier<ErrorModel>{
ErrorNotifier() : super(ErrorModel(showError: false, exception: '', errorTitle: ''));

void createException({
required String exception,
required String errorTitle
}){
state = state.update(showError: true, exception: exception, errorTitle: errorTitle);
}

void disbandError() {
state = state.update(showError: false);
}
}

class ErrorModel {
bool showError;
String exception;
String errorTitle;

ErrorModel({
required this.showError,
required this.exception,
required this.errorTitle,
});

ErrorModel update({bool? showError, String? exception, String? errorTitle}) {
return ErrorModel(
showError: showError ?? this.showError,
exception: exception ?? this.exception,
errorTitle: errorTitle ?? this.errorTitle,
);
}
}

final errorProvider = StateNotifierProvider<ErrorNotifier, ErrorModel>(
(ref) => ErrorNotifier(),
);


So whenever the showError changes to true i want to display modal windwow from the base widget thus making the error handling global to all pages using the base widget, but i need to change the data to the error model via the other StateNotifiers. For example in this StateNotifier: 

class OnboardingNotifier extends StateNotifier<bool> {
OnboardingNotifier() : super(SharedPreferencesService().getOnboarding());

void getOnboarding() {
state = SharedPreferencesService().getOnboarding();
}

Future<void> setOnboarding(bool onboarding) async {
await SharedPreferencesService().setOnboarding(onboarding);
}
}


I want to add try and catch blocks in every method and whenever i catch error to read the ErrorHandlin provider and change the showError value to true and be watched from the base widget. I imagined something like that:


void getOnboarding() {
state = SharedPreferencesService().getOnboarding();
try {
state = SharedPreferencesService().getOnboarding();
} catch(e){
ref.read(errorProvider.notifier).update(showError: true, exception: e, errorTitle: "Error occured")
}
}

Future<void> setOnboarding(bool onboarding) async {
try {
await SharedPreferencesService().setOnboarding(onboarding);
} catch(e){
ref.read(errorProvider.notifier).update(showError: true, exception: e, errorTitle: "Error occured")
}
}



I tried looking for possible solution but couldn&#39;t find similar questions nor anything in the documentation. I need to use the ErrorHandler provider in other StateNotifiers aswell and not just this one example.I would be very glad to haer someone did something like that or has better global error handling architecture.

</details>


# 答案1
**得分**: 0

Starting with Riverpod 2.0, there is a new notifier - AsyncNotifierProvider 和 [NotifierProvider][1]. 当从这个提供者扩展时,`Ref ref` 的一个实例将在类的所有地方都可用。

A quick solution to your problem would be to pass `ref` as a class field:

```dart
class OnboardingNotifier extends StateNotifier&lt;bool&gt; {
  OnboardingNotifier(this._ref) : super(SharedPreferencesService().getOnboarding());

  final Ref _ref;

  void getOnboarding() {
    state = SharedPreferencesService().getOnboarding();
    try {
      state = SharedPreferencesService().getOnboarding();
    } catch(e){
      _ref.read(errorProvider.notifier).update(showError: true, exception: e, 
  errorTitle: &quot;Error occured&quot;)
  }
}

}

And your provider will look like this:

final onboardingNotifier = StateNotifierProvider&lt;OnboardingNotifier, bool&gt;(
        (ref) =&gt; OnboardingNotifier(ref),
);

// or use tear-off

final onboardingNotifier = StateNotifierProvider&lt;OnboardingNotifier, bool&gt;(
        OnboardingNotifier.new
);

英文:

Starting with Riverpod 2.0 there is a new notifier - AsyncNotifierProvider and NotifierProvider. An instance of Ref ref will be available in all places in the class when extended from this provider.

A quick solution to your problem would be to pass ref as a class field:

class OnboardingNotifier extends StateNotifier&lt;bool&gt; {
  OnboardingNotifier(this._ref) : super(SharedPreferencesService().getOnboarding());

  final Ref _ref;

  void getOnboarding() {
    state = SharedPreferencesService().getOnboarding();
    try {
      state = SharedPreferencesService().getOnboarding();
    } catch(e){
      _ref.read(errorProvider.notifier).update(showError: true, exception: e, 
  errorTitle: &quot;Error occured&quot;)
  }
}

}

And your provider will look like this:

final onboardingNotifier = StateNotifierProvider&lt;OnboardingNotifier, bool&gt;(
        (ref) =&gt; OnboardingNotifier(ref),
);

// or use tear-off

final onboardingNotifier = StateNotifierProvider&lt;OnboardingNotifier, bool&gt;(
        OnboardingNotifier.new
);

huangapple
  • 本文由 发表于 2023年5月25日 20:19:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/76332201.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定