2020-03-20flutter 交互通信
把这几天了解学习的知识汇总了一下,掌握flutter以下几种方式即可应对各种场景了。
一、监听回调
场景,A页面实现回调方法并绑定自定义抽象类,在B页面触发回调A页面的回调方法。
import 'package:flutter/material.dart';
import 'package:scoped_model/scoped_model.dart';
void main() {
runApp(new RootLayout());
}
class RootLayout extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new RootLayoutM();
}
}
class RootLayoutM extends State<RootLayout> implements OnDialogClickListener {
String str = "show simple dialog";
String showMsg = "show simple dialog";
@override
void onOk() {
print('onOK');
setState(() {
showMsg = str + " onOK Click";
});
}
@override
void onCancel() {
print('onCancel');
setState(() {
showMsg = str + " onCancel Click";
});
}
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
body: new Center(
child:
new Text(showMsg, style: new TextStyle(color: Color(0xFF00FF00))),
),
floatingActionButton: new MyFloat(this),
));
}
}
//定义一个抽象类
abstract class OnDialogClickListener {
void onOk();
void onCancel();
}
class MyFloat extends StatelessWidget {
final OnDialogClickListener callback;
MyFloat(this.callback);
_showMyMaterialDialog(BuildContext context) {
print("_showMyMaterialDialog");
showDialog(
context: context,
builder: (context) {
return new AlertDialog(
title: new Text("title"),
content: new Text("内容内容内容内容内容内容内容内容内容内容内容"),
actions: <Widget>[
new FlatButton(
onPressed: () {
callback.onOk();
Navigator.of(context).pop();
},
child: new Text("确认"),
),
new FlatButton(
onPressed: () {
callback.onCancel();
Navigator.of(context).pop();
},
child: new Text("取消"),
),
],
);
});
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return new FloatingActionButton(
child: new Text("showDialog"),
onPressed: () {
_showMyMaterialDialog(context);
});
}
}
二、父页面调用子页面
这里使用全局key>GlobalKey来调用子页的方法或者公共属性.全局key比较耗能。谨慎使用。GlobalKey每个globalkey都是一个在整个应用内唯一的key。globalkey相对而言是比较昂贵的,如果你并不需要globalkey的某些特性,那么可以考虑使用Key、ValueKey、ObjectKey或UniqueKey。
注意:该场景是全局key,意思可以在任意地方使用。
用法:1.在即将被调用的页面声明接收构造方法,接收参数Globalkey。
2.在使用的页面,new一个有即将被调用页面状态的Globalkey,在生成被调用页面时传入这个globalkey,即可在使用页面随意调用被调用页的公共属性、方法!
其它key扩展,参考
ValueKey:以一个值为key。
ObjectKey:以一个对象为key。
UniqueKey:生成唯一的随机数作为key。
PageStorageKey:专用于存储页面滚动位置的key。
父页面.
class ParentScreen extends StatefulWidget {
@override
_ParentScreenState createState() => _ParentScreenState();
}
class _ParentScreenState extends State<ParentScreen> {
GlobalKey<_ChildScreenState> childKey = GlobalKey();
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
ChildScreen(
key: childKey
),
RaisedButton(
onPressed: (){
childKey.currentState.childFunction();
},
child: Text('点击我调用子组件方法'),
)
],
);
}
}
子页面.
class ChildScreen extends StatefulWidget {
ChildScreen({
Key key,
}) : super(key: key);
@override
_ChildScreenState createState() => _ChildScreenState();
}
class _ChildScreenState extends State<ChildScreen> {
@override
Widget build(BuildContext context) {
return Container(
);
}
childFunction(){
print('this is a childFunction');
}
}
三、数据监听
ValueListenableBuilder,监听数据变化(单个数值或者对象),比较适合组件的局部刷新。
使用场景,A页面点击item后刷新复选框,复选按钮等。还有收藏一件商品刷新购物车的右上角的件数。
也有人弄成多个地方的刷新,但个人觉得不适合,如果多地方还是考虑使用setstate,不能本末倒置,还是应该恰到好处。
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final ValueNotifier<int> _counter = ValueNotifier<int>(0);
final Widget goodJob = const Text('Good job!');
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title)
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('You have pushed the button this many times:'),
ValueListenableBuilder(
builder: (BuildContext context, int value, Widget child) {
// This builder will only get called when the _counter
// is updated.
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text('$value'),
child,
],
);
},
valueListenable: _counter,
// The child parameter is most helpful if the child is
// expensive to build and does not depend on the value from
// the notifier.
child: goodJob,
)
],
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.plus_one),
onPressed: () => _counter.value += 1,
),
);
}
}
四、正常传参
场景,A页面传值给B页面,B页面返回数值。例如,选择日期,返回选中值
这类比较普通就放最后了
如果单纯A传B,只需要在A页面构造函数中声明参数,q
且:
Navigator.push(context, new MaterialPageRoute<void> (
return A(name:xxx);
));
如果需要B返回值,既可以
await Navigator.pushNamed(context,'/router/文件名').then((value){print(value);// --> abc});