前端开发的传值也是必须的,比如说跳转传值啊,这些再普通不过,在一切皆widget中Flutter中同样是必须要掌握的知识点
先介绍下Flutter中Eventbus的使用,Eventbus这个词语在Android过来的朋友再熟悉不过了,它用于Android的事件发布-订阅总线,应用程序内各个组件之间进行通信,那么在flutter中也可以这么理解的,下面通过实例介绍它的使用吧。
导入框架
dependencies:
flutter:
sdk: flutter
#event_bus框架
event_bus: ^1.1.0
下面直接举个简单的例子吧,通过EventBusTest 2回传id值给EventBusTest

EventBusTest 的源码
import 'dart:async';
import 'package:flutter/material.dart';
import 'eventbus_manager/EventBusManage.dart';
import 'test_eventsbus2.dart';
class EventBusTest extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return EventBusState();
}
}
class EventBusState extends State<EventBusTest> {
var id = "";
BuildContext mContext;
StreamSubscription _subscription;
@override
void initState() {
// TODO: implement initState
super.initState();
//监听传id事件
_subscription =
JohwenEvent. eventBus.on<IdEvent>().listen((IdEvent data) => show(data.id));
_subscription.resume();
}
//刷新id
void show(String val) {
print("接收" + val);
setState(() {
id = val;
});
}
@override
Widget build(BuildContext context) {
// TODO: implement build
print("接收${id} ");
return Scaffold(
appBar: AppBar(
title: Text("eventbus接收"),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Builder(builder: (context) {
return Text("EventBus回传的id: ${id}");
}),
RaisedButton(
onPressed:(){
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => EventBusTest2()));
},
color: Colors.blue[400],
child: new Text('eventbus发送',
style: new TextStyle(color: Colors.white)),
),
],
),
);
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
_subscription.cancel(); // 一定要取消 避免内存泄露
}
}
EventBusTest 2源码
import 'package:flutter/material.dart';
import 'eventbus_manager/EventBusManage.dart';
class EventBusTest2 extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return EventBusState2();
}
}
class EventBusState2 extends State<EventBusTest2>{
TextEditingController idController = new TextEditingController();
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text("eventbus发送"),
),
body:Column(
children: <Widget>[
new TextField(
controller: idController,
decoration: new InputDecoration(hintText: 'eventbus测试传id'),
),
RaisedButton(
onPressed: (){
///这里开始传值 调用fire方法
eventBus.fire(IdEvent(idController.text.toString()));
print("发送"+idController.text.toString());
},
color: Colors.blue[400],
child: new Text('发送消息',
style: new TextStyle(color: Colors.white)),
)
],
) ,
);
}
}
初始化eventbus和事件
import 'package:event_bus/event_bus.dart';
//EventBus eventBus = new EventBus();
EventBus eventBus = new EventBus();
/// Event 模拟传值 id
class IdEvent {
String id;
IdEvent(this.id);
}
这里我们需要注意的主要就几个知识点
1,EventBus其核心是基于Dart Streams(流),在这里定义了StreamSubscription _subscription;相当于订阅者, 所以要取消订阅,防止内存泄漏。如果想详细理解flutter 中Stream流,要详细看下其他篇章。
2,eventBus 的订阅方法fire ,万变不离其中,这里照着例子去做你想做的就行啦。
**Flutter导航,路由,传值的方式 **
1,通过 Navigator.pushNamed 导航。
先定义路由名称
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
child: MaterialApp(
title: 'scoped',
theme: ThemeData.dark(),
home: TopPage(),
routes: {
// 'objectRoute': (BuildContext context) => new ObjectPage(title: '数据操作'),
'refresh': (BuildContext context) => new MainPage(),
'login': (BuildContext context) => new LoginPage(),
'objectRoute': (BuildContext context) => new ObjectPage(title: '数据操作'),
// 'indexpage': (BuildContext context) => new IndexPage(),
},
),
);
}
}
使用
Navigator.pushNamed(context, "objectRoute");
2,通过Navigator.push
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AddThing()));
},
3,返回上一级页面
Navigator.of(context).pop();
4,命名路由如何进行传值
这里摘自 https://cloud.tencent.com/developer/article/1489372
import 'package:flutter/material.dart';
import 'package:flutter_app_google/pages/SearchPage.dart';
import 'pages/tabs/Tabs.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
//配置命名路由信息
final routes = {
//如果需要传参,那么在配置的时候加上{arguments};如果不需要传参,则不用加{arguments}
"/search": (context, {arguments}) => Searchpage(arguments: arguments,),
};
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Tabs(),
//统一处理命名路由
onGenerateRoute: (RouteSettings settings) {
final String name = settings.name;
final Function pageContentBuilder = this.routes[name];
if (pageContentBuilder != null) {//能寻找到对应的路由
if (settings.arguments != null) {//页面跳转前有传参
final Route route = MaterialPageRoute(
builder: (context) => pageContentBuilder(context,
arguments: settings.arguments));
return route;
} else {//页面跳转前没有传参
final Route route = MaterialPageRoute(
builder: (context) => pageContentBuilder(context));
return route;
}
}
});
}
}
第二步
import 'package:flutter/material.dart';
class Searchpage extends StatelessWidget {
final arguments;//用于接收命名路由传递过来的参数值
const Searchpage({Key key, this.arguments}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(//在最底层采取Scaffold组件
appBar: AppBar(
title: Text("搜索页面"),
),
//获取命名路由传递过来的参数值
body: Text("Search Page!传递过来的参数值是:${arguments != null ? arguments['info'] : '默认值'}"),
floatingActionButton: FloatingActionButton(
onPressed: (){
//返回上一级页面
Navigator.of(context).pop();
},
child: Text("back"),
),
);
}
}
第三步
Navigator.pushNamed(context, "/search", arguments: {"info":"777"});
现在我们已经了解了命名路由传值该怎么去操作了,但是此时的代码看起来很乱,如果后期需要管理的命名路由多了,那么如果不做代码分离,而是直接像上面那样写的话,就会造成代码堆积,可读性变差,也不利于后期维护。所以,我们有必要做代码分离,那么该如何去做呢?
第1步,在lib文件夹下新建一个routes文件夹,然后在routes文件夹下新增一个 Routes.dart 文件
第2步 普通路由执行跳转页面的关键代码如下:
//Routes.dart
import 'package:flutter/material.dart';
import 'package:flutter_app_google/pages/SearchPage.dart';
//配置命名路由信息
final routes = {
//如果需要传参,那么在配置的时候加上{arguments};如果不需要传参,则不用加{arguments}
"/search": (context, {arguments}) => Searchpage(
arguments: arguments,
),
};
//统一处理命名路由
var onGenerateRoute = (RouteSettings settings) {
final String name = settings.name;
final Function pageContentBuilder = routes[name];
if (pageContentBuilder != null) {
//能寻找到对应的路由
if (settings.arguments != null) {
//页面跳转前有传参
final Route route = MaterialPageRoute(
builder: (context) =>
pageContentBuilder(context, arguments: settings.arguments));
return route;
} else {
//页面跳转前没有传参
final Route route =
MaterialPageRoute(builder: (context) => pageContentBuilder(context));
return route;
}
}
};
第3步 在main.dart中引入Routes.dart,并且使用暴露出来的接口
import 'package:flutter/material.dart';
import 'package:flutter_app_google/routes/Routes.dart' as prefix0;
import 'pages/tabs/Tabs.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Tabs(),
//统一处理命名路由
onGenerateRoute: prefix0.onGenerateRoute);
}
}
现在我已经将命名路由的配置代码分离到 Routes.dart 文件中了,这样一分离,main.dart中的代码就简洁多了。其实,我们还可以对main.dart中的代码进一步进行优化,也就是说,我们还可以将 Tabs 这个主页面也通过命名路由进行管理,代码如下:
/Routes.dart
//配置命名路由信息
final routes = {
//如果需要传参,那么在配置的时候加上{arguments};如果不需要传参,则不用加{arguments}
"/": (context) => Tabs(),
"/search": (context, {arguments}) => Searchpage(arguments: arguments),
};
//main.dart
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
// home: Tabs(),
initialRoute: "/",//初始化的时候加载的路由
//统一处理命名路由
onGenerateRoute: prefix0.onGenerateRoute);
}
}
最后,我们再来看看有状态的组件如何进行路由传值:
import 'package:flutter/material.dart';
class DetailPage extends StatefulWidget {
final Map arguments;//1,定义传值参数
DetailPage({Key key, this.arguments}) : super(key: key);//2,重新写构造函数
_DetailPageState createState() => _DetailPageState(arguments: arguments);//3,将参数值传递给_DetailPageState
}
class _DetailPageState extends State<DetailPage> {
Map arguments;//4,定义传值参数
_DetailPageState({this.arguments});//5,重新写构造函数
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("详情页面")),
body: Text("hulalaDetail!~${this.arguments["name"]}")//6,获取到传递过来的值
);
}
}
好了 这个篇章Flutter开发的传值(Eventbus)、导航和路(Navigater,Router),大体就总结到这里了,有不对的,欢迎指正
网友评论