我有三个页面,A、B、C,我通过抽屉在它们之间导航。
我的目标是让 initState 只被调用一次(当页面被插入 widget 树时),这样当我返回它时每个页面的状态都不会重新初始化。
我的第一个尝试是使用
Navigator.of(context).PushNamed(routeName)
,如下面的代码所示。
可能这不起作用,因为如果我从 A 调用 B 然后再调用 A,导航器堆栈是
[A] --> [B, A] --> [A, B, A] 而不是
[A] -> [B, A] --> [A]
所以基于pop()的导航应该更合适。我试过
onTap: () {
Navigator.of(context).canPop()
? Navigator.of(context)
.popUntil(ModalRoute.withName(PageA.routeName))
: Navigator.of(context).pushNamed(PageA.routeName);
},
代替
onTap: () => Navigator.of(context).pushNamed(PageA.routeName)
但它不起作用:当我点击抽屉项目时,出现黑屏,没有任何异常或警告,就好像导航器调用了一个黑屏......
我做错了什么?知道如何解决吗?
这是我的代码:
main.dart
import 'package:flutter/material.dart';
import 'page_c.dart';
import 'page_a.dart';
import 'page_b.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Navigation test',
home: PageA(),
routes: {
PageA.routeName: (ctx) => PageA(),
PageB.routeName: (ctx) => PageB(),
PageC.routeName: (ctx) => PageC(),
},
);
}
}
my_drawer.dart
import 'package:flutter/material.dart';
import 'page_b.dart';
import 'page_c.dart';
import 'page_a.dart';
class MyDrawer extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Drawer(
child: Column(
children: [
SizedBox(
height: 100,
),
ListTile(
title: Text('PAGE A'),
onTap: () => Navigator.of(context).pushNamed(PageA.routeName)),
ListTile(
title: Text('PAGE B'),
onTap: () => Navigator.of(context).pushNamed(PageB.routeName)),
ListTile(
title: Text('PAGE C'),
onTap: () => Navigator.of(context).pushNamed(PageC.routeName)),
],
),
);
}
}
page_a.dart
import 'package:flutter/material.dart';
import 'my_drawer.dart';
class PageA extends StatefulWidget {
static const routeName = '/route-a';
@override
_PageAState createState() => _PageAState();
}
class _PageAState extends State<PageA> {
@override
void initState() {
print('PAGE A INIT STATE');
super.initState();
}
// void didChangeDependencies() {
// print('PAGE A DID CHANGE DEPENDECIES');
// super.didChangeDependencies();
// }
// @override
// void dispose() {
// print('PAGE A DISPOSE');
// super.dispose();
// }
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('PAGE A')),
drawer: MyDrawer(),
body: Center(
child: Text('A', style: TextStyle(fontSize: 100)),
),
);
}
}
page_b.dart
import 'package:flutter/material.dart';
import 'my_drawer.dart';
class PageB extends StatefulWidget {
static const routeName = '/route-b';
@override
_PageBState createState() => _PageBState();
}
class _PageBState extends State<PageB> {
@override
void initState() {
print('PAGE B INIT STATE');
super.initState();
}
// void didChangeDependencies() {
// print('PAGE B DID CHANGE DEPENDECIES');
// super.didChangeDependencies();
// }
// @override
// void dispose() {
// print('PAGE B DISPOSE');
// super.dispose();
// }
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('PAGE B')),
drawer: MyDrawer(),
body: Center(
child: Text('B', style: TextStyle(fontSize: 100)),
),
);
}
}
page_c.dart
import 'package:flutter/material.dart';
import 'my_drawer.dart';
class PageC extends StatefulWidget {
static const routeName = '/route-c';
@override
_PageCState createState() => _PageCState();
}
class _PageCState extends State<PageC> {
@override
void initState() {
print('PAGE C INIT STATE');
super.initState();
}
// void didChangeDependencies() {
// print('PAGE C DID CHANGE DEPENDECIES');
// super.didChangeDependencies();
// }
// @override
// void dispose() {
// print('PAGE C DISPOSE');
// super.dispose();
// }
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('PAGE C')),
drawer: MyDrawer(),
body: Center(
child: Text('C', style: TextStyle(fontSize: 100)),
),
);
}
}
根据图像,一个 flutter stack 正在工作。已经将屏幕添加到堆栈中。如果你添加 B,它只会被推到 A 之上。现在,B 和 A 在堆栈中。现在,A也处于直播状态。 B也处于直播状态。 B 将是您可见的状态屏幕。而在后台A也处于运行状态。 A不会被处置。
解决方案:
你应该使用
Navigator.popAndPushNamed(context, B.id);
,通过使用 popAndPushNamed 方法,你可以从堆栈中删除 A,B 将成为活动屏幕。