访问立方体(Flutter)中的构建上下文



主要问题

你好!在Flutter中,我使用BLoC,更具体地说是肘来管理我的应用程序的状态。

我的weather_state.dart文件中有几个状态:

  • WeatherInitial
  • 天气荷载
  • 受天气影响
  • WeatherError

对于后者,当状态从weather_cubit.dart(最后一行)发出时,我想传递一条错误消息,正如您在该方法中看到的那样:

Future<void> getWeather(String cityName) async {
emit(const WeatherLoading());
try {
final weather = await _weatherRepository.fetchWeather(cityName);
emit(WeatherLoaded(weather));
} on NetworkException {
emit(const WeatherError('Error fetching the data.'));
}
}

现在,我只是本地化了我的应用程序,因此也想本地化错误消息。我在cubit中导入了必要的包,然后以这种方式访问本地化的错误消息:

emit(WeatherError(AppLocalizations.of(context)!.errorFetchingData));

我得到以下错误:Undefined name 'context'.
很明显,我理解为什么,但我的问题是:
我如何从立方体内部访问上下文
如果有多种方法,那么最优化的方法是什么?

附言:如果你有一个不错的解决方法,也可以随意提及

我的发现:

显然,从这个资源中,我发现以这种方式提供上下文(这里,在我的home_screen.dart中):

return BlocProvider<WeatherCubit>(
create: (context) => WeatherCubit(),
child: MaterialApp(

本应该让它放在我的隔间里。你可以猜到,这对我不起作用。顺便说一句,我正在寻找比在cubit构造函数中提供上下文作为参数更好的东西(因为这对以后的测试来说真的很痛苦)。

编辑

我知道我可以在方法中作为String参数传递错误消息。我也已经在我的WeatherError状态中使用了一个错误消息属性
我的问题是,错误消息取决于方法本身的行为,这不可能在内部传递参数。

我之前举了一个简单的例子,但我将在那里提供另一个例子:
假设我有一个从二维码扫描中得到的UUID
我将UUID作为selectCity方法的参数进行传递:

void selectCity(String? cityUuid) async {
const uuidPattern =
r'[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}';
final regexUuid = RegExp(uuidPattern);
if (cityUuid == null) {
emit(CitySelectionError('The QR code scanner had an error. Please try again.'));
} else if (!regexUuid.hasMatch(cityUuid)) {
emit(CitySelectionError('The QR code does not contain a UUID and cannot match a city.'));
} else {
emit(CitySelected(cityUuid));
}
}

错误状态:

class CitySelectionError extends CityState {
final String errorMessage;
CitySelectionError(this.errorMessage) : super(null);
// Equatable: don't mind
@override
List<Object?> get props => [errorMessage];
}

在检查字符串是否是实际的UUID之前,我首先想检查它是否为null,因为这将是扫描失败的结果
正如您所看到的,错误消息显然取决于方法实现。这意味着我不能将错误消息作为参数传递;这毫无意义
知道我缺了什么吗?

Idk如果发送上下文是个好主意(让我们将树的上下文留给您的小部件,而不是逻辑),在我的情况下,我只发送错误而不发送消息:

emit(const WeatherError());

现在,在监听器(如果您想显示Snackbar)中,您收听该状态,然后显示翻译:

return BlocListener<BlocA, StateA>(
listener: (context, state) {
if (state is WeatherError) {
ScaffoldMessenger.of(context)
..showSnackBar(
SnackBar(
content: Text(AppLocalizations.of(context)!.errorFetchingData),
),
);
}
},
child: ...

编辑:

是的,逻辑是这样的(除非你已经在寻找更好地处理错误的方法),但在这种情况下,我们会设置条件,但我们会发送一个密钥,帮助你找到要查找的翻译。

void selectCity(String? cityUuid) async {
const uuidPattern =
r'[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}';
final regexUuid = RegExp(uuidPattern);
if (cityUuid == null) {
emit(CitySelectionError('qrError'));
} else if (!regexUuid.hasMatch(cityUuid)) {
emit(CitySelectionError('qrNoMatch'));
} else {
emit(CitySelected(cityUuid));
}
}

在您的监听器中,在AppLocalization中,您将有一个名为translate()的方法,在该方法中,您可以发送该密钥,并通过.json进行翻译,但为此,我给您留下了一个更好的答案:

Flutter 中的字符串xml文件

return BlocListener<BlocA, StateA>(
listener: (context, state) {
if (state is CitySelectionError) {
ScaffoldMessenger.of(context)
..showSnackBar(
SnackBar(
content: Text(AppLocalizations.of(context)!.translate(state.errorMessage)),
),
);
}
},
child: ...

我希望它能更好地修复或优化您的代码:)

错误是正常的,因为CubitWidget无关,也不对build负责。

如何从立方体内部访问上下文?

要严格回答您的问题,为了在Cubit中使用context,您可以在创建Cubit时将其作为参数传递。

类似以下内容:

return BlocProvider<WeatherCubit>(
create: (context) => WeatherCubit(context),
child: MaterialApp(

因此WeatherCubit应该看起来像:

class WeatherCubit extends Cubit<WeatherState> {
final BuildContext context;
WeatherCubit(this.context) : super(WeatherState());
}

但是,如果目的是向用户显示错误消息,例如在SnackBar中,我建议您使用BlocListener(如果您也需要BlocBuilder,则使用BlocConsumer)来处理这种副作用。通过这样做,您可以明确划分责任,并尊重BLoC模式的理念。

BlocListener<WeatherCubit, WeatherState>(
listenWhen: (previous, current) => previous != current,
listener: (context, state) {
if (state is WeatherError) {
ScaffoldMessenger.of(context)..hideCurrentSnackBar()..showSnackBar(SnackBar(content: Text(state.errorMessage)));
}
},
child: child,
),

最后,WeatherError:

class WeatherError extends WeatherState {
final String errorMessage;
const WeatherError({required this.errorMessage});
}

这样,当当前state is WeatherError时,您可以使用state.errorMessage访问errorMessage

最新更新