• 主页
  • 归档
  • 分类
  • 照片墙
所有文章 友情链接 关于我

  • 主页
  • 归档
  • 分类
  • 照片墙
  1. 1. 命名路由
  2. 2. 路由传参
  3. 3. 组件之间的共享状态

Flutter路由

2019-11-10 10:06:41
总字数 1.3k
预计阅读时间 6 分钟

使用MaterialPageRoute也就是页面路由,可以实现不同Widget之间的跳转
页面只是一个全屏的Widget

先写好另一个页面的Widget

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class DetailPage extends StatefulWidget {
DetailPage({Key key, this.title}) : super(key: key);
final String title;
@override
_DetailPageState createState() => _DetailPageState();
}

class _DetailPageState extends State<DetailPage> {
@override
Widget build(BuildContext context) {

return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Text('这里是另一个页面')
);
}
}

简单的页面跳转

1
2
3
Navigator.push(context, MaterialPageRoute(builder: (_){
return DetailPage(title: 'detail page');
}));

既然是push,那么就是个栈模型了,跳转到另一个页面相当于入栈
如果要返回到上一级页面可以这样做,pop相当于是出栈

1
Navigator.pop(context);

命名路由

可以在MaterialApp当中传入routes参数,该参数是一个Map对象
key是路由名称,value是返回组件对象的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.brown,
),
routes: {
'/' : (context) => MyHomePage(title: 'Flutter Demo Home Page'),
'/detail' : (context) => DetailPage(title: 'detail page')
},
initialRoute: '/',
);
}
}

通常的习惯当然是把routes这部分封装在一个单独的模块当中引入使用

命名路由的跳转

1
Navigator.pushNamed(context, '/detail');

这种方式不需要反复构建和销毁组件对象,相对来讲是更好的一种方式

路由传参

基本的Navigator.push的方式是构建组件,当然可以给组件的构造方法传入参数,比如上面传入的title
这个就不需要特别的传参方式了,如果使用命名路由跳转
可以传入第三个可选参数arguments

1
Navigator.pushNamed(context, '/detail', arguments: {'id': 1001});

arguments可以是任意的Object

接收参数方式

1
ModalRoute.of(context).settings.arguments

当然不论传入的是什么,此时获取到的还是Object类型,需要使用as Map<String, int>(取决于传入的类型而执行的类型推导)
进行强制类型转换

组件之间的共享状态

除了组件之间的传参,以及路由的传参之外,组件之间通常需要有一些状态需要共享
比如一个常见的需求是用户登录之后,在每个页面上都能看到当前登录的用户是什么名字

需要使用到的是provider这个第三方模块

先定义Model

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// user.dart
import 'package:json_annotation/json_annotation.dart';

part 'user.g.dart';

@JsonSerializable()
class User {
User({this.username, this.createdAt, this.updatedAt});

String username;
String createdAt;
String updatedAt;

factory User.fromJson(Map<String,dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}

还有

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// user.g.dart
part of 'user.dart';

User _$UserFromJson(Map<String, dynamic> json) {
return User(
username: json['username'] as String,
createdAt: json['createdAt'] as String,
updatedAt: json['updatedAt'] as String,
);
}

Map<String, dynamic> _$UserToJson(User instance) => <String, dynamic>{
'username': instance.username,
'createdAt': instance.createdAt,
'updatedAt': instance.updatedAt,
};

为了能够在启动时读取上次运行的缓存
需要使用shared_preferences这个第三方模块

定义全局对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// global.dart
class Global {
static SharedPreferences _prefs;
static Profile profile = Profile();

// 是否为release版
static bool get isRelease => bool.fromEnvironment("dart.vm.product");

//初始化全局信息,会在APP启动时执行
static Future init() async {
_prefs = await SharedPreferences.getInstance();
var _profile = _prefs.getString("profile");
if (_profile != null) {
try {
profile = Profile.fromJson(jsonDecode(_profile));
} catch (e) {
print(e);
}
}

// 如果没有缓存策略,设置默认缓存策略
profile.cache = profile.cache ?? CacheConfig()
..enable = true
..maxAge = 3600
..maxCount = 100;
}

// 持久化Profile信息
static saveProfile() =>
_prefs.setString("profile", jsonEncode(profile.toJson()));
}

// profile.dart
@JsonSerializable()
class Profile {
Profile({this.user, this.token, this.theme, this.cache, this.lastLogin,
this.locale});

User user;
String token;
CacheConfig cache;
String lastLogin;
String locale;

factory Profile.fromJson(Map<String,dynamic> json) => _$ProfileFromJson(json);
Map<String, dynamic> toJson() => _$ProfileToJson(this);
}

profile当中可以持有User对象
这种情况下就需要在应用启动时就初始化Global对象

1
void main() => Global.init().then((e) => runApp(MyApp()));

自定义Notifier

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class ProfileChangeNotifier extends ChangeNotifier {
Profile get _profile => Global.profile;

@override
void notifyListeners() {
Global.saveProfile(); //保存Profile变更
super.notifyListeners(); //通知依赖的Widget更新
}
}

/// 用户状态在登录状态发生变化时更新、通知其依赖项
class UserModel extends ProfileChangeNotifier {
User get user => _profile.user;

// APP是否登录(如果有用户信息,则证明登录过)
bool get isLogin => user != null;

//用户信息发生变化,更新用户信息并通知依赖它的子孙Widgets更新
set user(User user) {
if (user?.username != _profile.user?.username) {
_profile.lastLogin = _profile.user?.username;
_profile.user = user;
notifyListeners();
}
}
}

根组件需要使用InheritedProvider进行包装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return InheritedProvider<UserModel>(
value: UserModel(),
child: MaterialApp(
title: 'My App',
theme: ThemeData(
primarySwatch: Colors.pink,
),
routes: {
'login' : (context) => Login(title: '登录'),
'home' : (context) => Home(title: '首页')
},
initialRoute: 'login',
),
);
}
}

共享状态的更新,比如在登录时,需要把当前用户的信息写入profile,并且传播到各个组件当中
这里简单写入一个username作为例子

1
Provider.of<UserModel>(context).user = User.fromJson({'username': _usernameController.text});
  • flutter
  • dart
  • flutter

扫一扫,分享到微信

Flutter踩坑记录
Flutter动态列表 
© 2024 夏夜梦星辰
鲁ICP备19028444号
Power By Hexo
  • 所有文章
  • 友情链接
  • 关于我
{{searchItem.query}}
标签: 分类:
  • maven
  • 持续集成
  • JMS
  • 线程
  • JavaScript
  • ECMAScript6
  • 单元测试
  • Promise
  • Web Worker
  • 函数
  • prototype
  • 模块化
  • 正则表达式
  • 数据库
  • MongoDB
  • 索引
  • 集群
  • 全文检索
  • flutter
  • dart
  • git
  • 版本控制
  • linux
  • shell
  • docker
  • nginx
  • jenkins
  • opencv
  • vim
  • react
  • react native
  • 前端
  • css
  • HTML5
  • Hexo
  • sass
  • Three.js
  • TypeScript
  • Vue
  • 组件化
  • base64
  • webpack
  • nodejs
  • gulp
  • TensorFlow
  • 机器学习
  • 算法
  • 动态规划
  • 数据结构
  • Java
  • JavaScript
  • MongoDB
  • flutter
  • Git
  • linux
  • react
  • 前端杂烩
  • 男生女生
  • 算法
  • 十年饮冰,难凉热血
  • †少女癌†
  • 猫与向日葵
  • coderfun
  • JENKINS
  • API管理后台
愿你最终能接纳每一面每一种的自己
独自活着便是团圆