Flutter Push 与 State 相关的视图

Flutter Push vs. State-related views

有两种方法可以更改用户在显示上看到的内容:我可以推送到另一个页面,或者我可以更改有状态小部件的状态并重建它。你能告诉我,哪种方式是最佳做法吗? (如果它取决于 - 我猜 - 取决于什么?)

推动:

class Pushing extends StatelessWidget {

@override
Widget build(BuildContext context) {
return Scaffold(
  body: Center(
      child: RaisedButton(
        onPressed: () => Navigator.push(context, new MaterialPageRoute(builder: (context) => new SecondPage())),)
  ),
);
}
}

使用状态

class UsingStates extends StatefulWidget {
@override
State createState() => new _UsingStatesState();
}

class _UsingStatesState extends State<UsingStates> {
 bool isPageTwo;

 @override
 void initState() {
  isPageTwo = false;
  super.initState();
 }

 @override
 Widget build(BuildContext context) {
 return Scaffold(
   body: isPageTwo ? Center(child: Text('Page two')) : Center(child: RaisedButton(onPressed: () {
    setState(() {
      isPageTwo = true;
    });
  })),
);
}
}
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
 @override
Widget build(BuildContext context) {
return new MaterialApp(
  title: 'Flutter Demo',
  theme: new ThemeData(
    primarySwatch: Colors.blue,
  ),
  home: new Page1(title: 'Flutter Demo Home Page'),
);
}
}
class Page1 extends StatefulWidget {
Page1({Key key, this.title}) : super(key: key);
final String title;

@override
Page1State createState() => new Page1State();
}
class Page1State extends State<Page1> {
StreamController<int> streamController = new StreamController<int>();
@override
Widget build(BuildContext context) {
return new Scaffold(
  appBar: new AppBar(
    title: new Text(widget.title),
  ),
  body: new Center(
    child: new RaisedButton(child: new Text("This is Page 1, Press here to go to page 2"),onPressed:()=>streamController.add(2) ,),
  ),
);
}
@override
void initState() {
streamController.stream.listen((intValue){
  print("Page 1 stream : "+intValue.toString());
  if(intValue==2){
    Navigator.of(context).push(new MaterialPageRoute(builder: (context)=>Page2(title: "Page 2",)));
  }
});
super.initState();
}
@override
void dispose() {
streamController.close();
super.dispose();
}
}
class Page2 extends StatefulWidget {
Page2({Key key, this.title}) : super(key: key);
final String title;
@override
Page2State createState() => new Page2State();
}
class Page2State extends State<Page2> {
StreamController<int> streamController = new StreamController<int>();
@override
Widget build(BuildContext context) {
return new Scaffold(
  appBar: new AppBar(
    title: new Text(widget.title),
  ),
  body: new Center(
    child: new RaisedButton(child: new Text("This is Page 2, Press here to go to page 2"),onPressed:()=> streamController.add(1),),
  ),
 );
 }
 @override
 void initState() {
 streamController.stream.listen((intValue){
  print("Page 2 stream : "+intValue.toString());
  if(intValue==1){
    Navigator.of(context).push(new MaterialPageRoute(builder: (context)=>Page1(title: "Page 1",)));
  }
  });
  super.initState();
  }


  @override
  void dispose() {
   streamController.close();
  super.dispose();
  }
  }

抱歉格式错误。您可以 运行 此代码而无需任何依赖项。希望对您有所帮助

答案当然是:视情况而定。

何时使用Navigator

使用导航器推送的路线在某种程度上等同于...

  • Activity 和 Android
  • 中的 Fragment
  • Angular 或 React
  • 中的路由
  • 一个html个经典网页文件

您将使用 Navigator 在您应用程序的逻辑独立部分之间切换。想想带有不同页面的 Whosebug 应用程序,例如"Question List"、"Question Detail"、"Ask Question" 形式和 "User Profile".

Navigator 负责后退导航(android 手机上的硬件后退按钮 + AppBar 中的后退箭头)

请注意,路线不必覆盖整个屏幕。 showDialog 也在内部使用 Navigator.push()(这就是为什么您使用 Navigator.pop() 关闭对话框。

类似于Android上的startActivityForResult,路由也可以return调用pop时的结果。考虑一个让您选择日期的对话框。

何时使用State

当屏幕是一个逻辑单元时使用State,例如:

  • 当您从服务器加载项目列表时,您将有 4 种不同的状态:
    • 正在加载
    • "An error occured..."
    • 列表为空时显示的占位符
    • ListView
  • 具有多个步骤的表单
  • 具有多个选项卡的屏幕(在这种情况下,导航由选项卡栏处理)
  • 在向服务器发送 POST 请求时 "Please wait" 覆盖屏幕阻塞屏幕

毕竟 Navigator 也是一个跟踪路线历史记录的 StatefulWidget。有状态小部件是 Flutter 的基本构建块。当您的应用程序非常复杂且 Navigator 不符合您的需求时,您可以随时创建自己的 StatefulWidget 以实现完全控制。

查看 Flutter 的源代码(Android Studio 中的 CTRL + B)总是有帮助的。