我在使用 block 监听器进行导航时遇到问题
我有五个导航屏幕,并且在每个文件中都使用 BlocConsumer。我正在 flutter 检查器中寻找粒度 View 。我使用 blocListener 进行导航。当我 pushNamed 第一个屏幕时,一切正常,我导航到第二个屏幕(第一个屏幕已添加到导航堆栈)。现在我在第二个屏幕,当我按下移动到第三个屏幕时,两个第二个屏幕,然后添加第三个屏幕,堆栈应该像这样 (第一个屏幕,第二个屏幕,第三个屏幕) 但不幸的是就像(第一个屏幕,第二个屏幕,第二个屏幕,第三个屏幕)。 现在,当我在第三个屏幕上并想要添加第四个屏幕时,它是堆栈,但添加了第二个屏幕,然后添加了第三个屏幕两个次,然后添加第四个屏幕。堆栈应该像这样(第一个屏幕,第二个屏幕,第三个屏幕,第四个屏幕),但不幸的是它就像(第一个屏幕,第二个屏幕,第二个屏幕,第三个屏幕,第二个屏幕,第三屏幕,第三屏幕,第四屏幕)。因此,导航堆栈中不是 4 个屏幕,而是 8 个屏幕。
这是我在所有文件中使用的模式。
这是我创建 bloc 实例并关闭它的地方。
class MyAppRoutes {
FieldsBloc _fieldsBloc = FieldsBloc();
Route onGenerateRoute(RouteSettings routeSettings) {
try {
switch (routeSettings.name) {
case LandingPage.routeName:
return MaterialPageRoute(builder: (_) => LandingPage());
case CategoryPage.routeName:
return MaterialPageRoute(
builder: (context) => BlocProvider.value(
value: _fieldsBloc,
child: CategoryPage(),
));
case ExpertisePage.routeName:
return MaterialPageRoute(
builder: (context) => BlocProvider.value(
value: _fieldsBloc,
child: ExpertisePage(),
));
case ExpertiseLevelPage.routeName:
return MaterialPageRoute(
builder: (context) => BlocProvider.value(
value: _fieldsBloc,
child: ExpertiseLevelPage(),
));
case EducationPage.routeName:
return MaterialPageRoute(
builder: (context) => BlocProvider.value(
value: _fieldsBloc,
child: EducationPage(),
));
default:
return null;
}
} catch (e) {
print(e);
}
}
void dispose() async {
_fieldsBloc.close();
}
}
这是我在每个文件中使用的小部件。
BlocConsumer<FieldsBloc, FieldsState>(builder: (context, state) {
if (state is FieldsInitial) {
return Container();
} else if (state is FieldLoadingState) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: getCircularProgress(context),
);
} else if (state is FieldSuccessfulState) {
return Container();
} else if (state is FieldUnsuccessfulState) {
return Padding(
padding: const EdgeInsets.all(15.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.error,
color: Colors.red,
),
SizedBox(
width: 5.0,
),
Expanded(
child: TextStyleRes.textStyleFont1(
textColor: Colors.red,
text: state.message,
fontSize: 12,
fontWeight: FontWeight.w700)),
],
));
}
return Container();
}, listener: (context, state) {
if (state is FieldSuccessfulState)
return SchedulerBinding.instance.addPostFrameCallback((_) {
Navigator.of(context).pushNamed(ExpertisePage.routeName);
});
}),
这是正在触发的 Bloc 事件。
abstract class FieldsEvent {}
class NextButtonEventScreen3 extends FieldsEvent {
List<String> categories;
NextButtonEventScreen3(this.categories);
}
class NextButtonEventScreen4 extends FieldsEvent {
List skills;
NextButtonEventScreen4(this.skills);
}
class NextButtonEventScreen5 extends FieldsEvent {
String expert;
NextButtonEventScreen5(this.expert);
}
这就是 Bloc 。
if (event is NextButtonEventScreen3) {
if (event.categories.isNotEmpty) {
yield FieldLoadingState();
categories = event.categories;
yield FieldSuccessfulState();
} else
throw ('Please choose at least 1 category');
}
//=====================SignUpScreen4===========================
else if (event is NextButtonEventScreen4) {
if (event.skills.isNotEmpty) {
yield FieldLoadingState();
skills = event.skills;
yield FieldSuccessfulState(_updateModel());
} else
throw ('Please provide at least 1 skill');
}
//=====================SignUpScreen5===========================
else if (event is NextButtonEventScreen5) {
expert = event.expert;
yield FieldSuccessfulState();
}
这些是 Bloc 内的州
abstract class FieldsState {
String message;
}
class FieldsInitial extends FieldsState {}
class FieldLoadingState extends FieldsState {}
class FieldSuccessfulState extends FieldsState {
var data;
FieldSuccessfulState([this.data]);
}
class FieldUnsuccessfulState extends FieldsState {
String message;
FieldUnsuccessfulState({this.message});
}
最佳答案
导航堆栈上的先前页面仍然存在,正在监听 block 事件。当第二个屏幕上的状态变为 FieldsSuccessfulState
时,两个监听器都会看到此情况并尝试导航到下一个屏幕。
为了确保只有当前屏幕会对 FieldsSuccessfulState
使用react,我可以想到两个选项:
将
FieldsSuccessfulState
拆分为多个结果(不同的类或添加的字段),并使每个屏幕仅对自己的成功状态使用react。在导航到下一个屏幕之前检查
ModalRoute.of(context).isCurrent
。这可以在监听器本身或listenWhen
参数中完成。
关于flutter - 将 BlocListener 与 Navigator PushNamed 一起使用会导致歧义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68137100/