我的应用程序中有两个屏幕。
屏幕 A 在打开时运行计算成本很高的操作,并通过在dispose()
调用时取消动画/订阅数据库来正确处理以防止内存泄漏。
从屏幕 A,您可以打开另一个屏幕(屏幕 B)。
当我使用 时Navigator.pushNamed
,屏幕 A 保留在内存中,dispose()
不会被调用,即使现在显示了屏幕 B。
有没有办法在屏幕 A 不在视野中时强制处理它?
永远不会处理第一条路线的示例代码:
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
title: 'Navigation Basics',
home: FirstRoute(),
));
}
class FirstRoute extends StatefulWidget {
@override
_FirstRouteState createState() => _FirstRouteState();
}
class _FirstRouteState extends State<FirstRoute> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Route'),
),
body: RaisedButton(
child: Text('Open route'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondRoute()),
);
},
),
);
}
@override
void dispose() {
// Never called
print("Disposing first route");
super.dispose();
}
}
class SecondRoute extends StatefulWidget {
@override
_SecondRouteState createState() => _SecondRouteState();
}
class _SecondRouteState extends State<SecondRoute> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Route"),
),
body: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go back!'),
),
);
}
@override
void dispose() {
print("Disposing second route");
super.dispose();
}
}
Run Code Online (Sandbox Code Playgroud)
Navigator.pushReplacement
在第一和第二屏幕之间路由时调用。
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
title: 'Navigation Basics',
home: FirstRoute(),
));
}
class FirstRoute extends StatefulWidget {
@override
_FirstRouteState createState() => _FirstRouteState();
}
class _FirstRouteState extends State<FirstRoute> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Route'),
),
body: RaisedButton(
child: Text('Open route'),
onPressed: () {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => SecondRoute()),
);
},
),
);
}
@override
void dispose() {
// Never called
print("Disposing first route");
super.dispose();
}
}
class SecondRoute extends StatefulWidget {
@override
_SecondRouteState createState() => _SecondRouteState();
}
class _SecondRouteState extends State<SecondRoute> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Route"),
),
body: RaisedButton(
onPressed: () {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => FirstRoute()),
);
},
child: Text('Go back!'),
),
);
}
@override
void dispose() {
print("Disposing second route");
super.dispose();
}
}
Run Code Online (Sandbox Code Playgroud)
尝试这个
在新版本的 flutter 中,deactivate
当您将新的小部件推到另一个小部件之上时,不会调用 flutter。flutter 的 github 上还有一个与此主题相关的未解决问题:https://github.com/flutter/flutter/issues/50147
处理此问题的最佳方法是添加RouteObserver<PageRoute>
到您的材料应用程序并覆盖didPushNext
和didPopNext
功能。
有一篇与此主题相关的非常有用的媒体文章,您可以在这里找到:https://medium.com/koahealth/how-to-track-screen-transitions-in-flutter-with-routeobserver-733984a90dea
正如文章所说创建你自己的RouteAwareWidget
,你可以将这两个回调添加到小部件的字段中:
didPopNext
didPushNext
class RouteAwareWidget extends StatefulWidget {
final Widget child;
final VoidCallback? didPopNext;
final VoidCallback? didPushNext;
const RouteAwareWidget({
Key? key,
required this.child,
this.didPopNext,
this.didPushNext,
}) : super(key: key);
@override
State<RouteAwareWidget> createState() => RouteAwareWidgetState();
}
class RouteAwareWidgetState extends State<RouteAwareWidget> with RouteAware {
@override
void didChangeDependencies() {
super.didChangeDependencies();
routeObserver.subscribe(this, ModalRoute.of(context) as PageRoute);
}
@override
void dispose() {
routeObserver.unsubscribe(this);
super.dispose();
}
@override
void didPush() {}
@override
void didPopNext() {
dPrint('didPopNext');
widget.didPopNext == null ? null : widget.didPopNext!();
super.didPopNext();
}
@override
void didPushNext() {
dPrint('didPushNext');
widget.didPushNext == null ? null : widget.didPushNext!();
super.didPushNext();
}
@override
Widget build(BuildContext context) => widget.child;
}
Run Code Online (Sandbox Code Playgroud)
创建一个全局RouteObserver<PageRoute>
并将其添加到您的材质应用程序中:
final RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();
MaterialApp(
navigatorObservers: [routeObserver],
debugShowCheckedModeBanner: false,
routes: _routes,
)
Run Code Online (Sandbox Code Playgroud)
然后在您的路线中,您应该使用您的路线包装RouteAwareWidget
并添加您想要的自定义函数:
final _routes = {
HomePage.routeName: (context) => RouteAwareWidget(
child: const HomePage(),
didPushNext: () => sl<CameraBloc>().add(Dispose()),
didPopNext: () => sl<CameraBloc>().add(Init()),
),
MyQuestions.routeName: (context) => const RouteAwareWidget(
child: MyQuestions(),
),
};
Run Code Online (Sandbox Code Playgroud)
didPushNext
当您将一个小部件推到主页顶部时将被调用,并且didPopNext
当您在主页上方弹出最后一个小部件时将被调用。
归档时间: |
|
查看次数: |
11388 次 |
最近记录: |