在过去的几天里,我正在做一个项目,并被 gorouter 的行为所困扰。下面我就来解释一下它是什么-
class ABCScreen extends StatelessWidget {
final String id;
const ABCScreen({super.key, required this.id});
@override
Widget build(BuildContext context) {
return Consumer<ABCState>(builder: (context, future, child) {
return FutureBuilder(
future: future.call(id: id),
builder: ((context, snapshot) {
if (snapshot.data != null &&
snapshot.connectionState == ConnectionState.done) {
return XYZScreen(model: snapshot.data!);
} else {
return const ShimmerScreen();
}
}),
);
});
}
}
因此 ABCScreen 基本上负责使用提供程序从 REST API 端点获取数据,并将数据传递到 XYZ Screen 进行构建。它还使用 FutureBuilder。这就是国家的样子 -
class ABCState extends ChangeNotifierProvider {
Future<Model?> call({required String id}) async {
Model? data = await ABCServices().fetchData(id: id); // REST API call
if (data != null) {
return data;
}
return null;
}
}
现在,我知道我没有将 API 结果存储到提供程序中的某个变量中,然后使用这些变量来构建屏幕,因为我正在通过未来的构建器获得所需的结果,但我不喜欢改变事情。
所以,GoRouter 的主要问题是从 XYZScreen ( ABCScreen 的子屏幕)产生的,该屏幕包含到另一个 QWEScreen 的导航路线(在 gorouter 路线配置中定义了路径,比如说 /path ),
另外,由于我使用 goRouter 作为我的应用程序的主要路由方法,所以我想坚持使用它并且不想使用 Navigator.push()。看来我在实现代码时遇到了一些错误。请看一下,任何帮助将不胜感激。提前谢谢你:)
class XYZScreen extends StatelessWidget {
const XYZScreen({
super.key,
required this.model,
});
final Model model ;
@override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
if (context.mounted) {
context.push('/path');
}
},
child: SomeContainer(model: model),
);
}
}
期望只是在导航中使用 goRouter,同时确保不会发生额外的调用/重建小部件。
我已经询问了 Flutter 成员,根据 issue,如果视图小部件不是 const 类,GoRouter 会按照预期行为重建视图。
您有两种解决方案来解决这个问题:
ABCScreen
成为 const 类,如果您仍然需要将参数传递给小部件,请考虑使用:
Provider
用于您案例中的全局状态管理。Provider
传递参数(不太适合复杂数据)。ABCScreen
设为 const 类时很有用(例如,需要动态初始化)。 GoRoute(
path: ABCScreen.routePath,
pageBuilder: (BuildContext context, GoRouterState state) {
final String parameter = state.extra as String;
return MaterialPage<void>(
child: Builder(builder: (BuildContext context) {
// FIXME:https://stackoverflow.com/a/56666801/5643911
// FIXME:https://github.com/flutter/flutter/issues/152906
if (state.matchedLocation != GoRouter.of(context).location) {
return const SizedBox.shrink();
}
return ABCScreen(id: parameter);
}),
);
},
),
希望答案为您的 Flutter 项目提供清晰的解决方案!