Flutter 如何在Flatter中的选项卡之间发送数据?
我有一个Flatter应用程序,有两个选项卡:一个用于管理和接收连续的数据流,另一个选项卡在数据进入时显示数据 如何将数据从第一个选项卡传递到第二个选项卡?我看到的大部分帖子都是关于在父级和子级之间传递数据,而不是子级到子级 我会使用Flutter 如何在Flatter中的选项卡之间发送数据?,flutter,dart,Flutter,Dart,我有一个Flatter应用程序,有两个选项卡:一个用于管理和接收连续的数据流,另一个选项卡在数据进入时显示数据 如何将数据从第一个选项卡传递到第二个选项卡?我看到的大部分帖子都是关于在父级和子级之间传递数据,而不是子级到子级 我会使用GlobalKey?有更好的选择吗 这是主要的构建功能: @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const
GlobalKey
?有更好的选择吗
这是主要的构建功能:
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('some text'),
bottom: TabBar(
tabs: tabs,
controller: _tabController,
),
),
body: TabBarView(
controller: _tabController,
children: [
InputManagment(),
InfiniteListView(),
],
),
);
}
在这种情况下,建议使用
InheritedWidget
这是非常全面的,包括一个
首先,您可能需要创建一个类来保存要共享的数据
import 'dart:async';
class MyInheritedWidgetData {
var sharedData;
int someCount;
String someMessage;
final StreamController _streamController = StreamController.broadcast();
Stream get stream => _streamController.stream;
Sink get sink => _streamController.sink;
}
我刚刚给这个类添加了一堆变量。你可以用你想要的任何东西填充它。现在,您还希望有一个保存该数据类的
InheritedWidget
class MyInheritedWidget extends InheritedWidget {
final MyInheritedWidgetData data;
MyInheritedWidget({
Key key,
@required Widget child,
}) : assert(child != null),
data = MyInheritedWidgetData(),
super(key: key, child: child);
static MyInheritedWidgetData of(BuildContext context) => (context.inheritFromWidgetOfExactType(MyInheritedWidget) as MyInheritedWidget).data;
@override
bool updateShouldNotify(MyInheritedWidget old) => false;
}
您需要将此MyInheritedWidget
放在小部件树的顶部,或者至少放在您提到的父小部件的上方。下面将说明必要的小部件层次结构
MyInheritedWidget
TabBarView
InputManagment
InfiniteListView
// in your build function this would be `body: MyInheritedWidget(child: TabBarView(...))`
现在,您只需在任何子窗口小部件中使用MyInheritedWidget.of(context)
即可访问数据类
您可能想考虑使用流来连续发送和侦听“数据流”。然而,这也只是数据类的一部分。为了给您一个想法,我在示例数据类中包含了stream变量。您可以使用
MyInheritedWidget.of(context).sink.add(..)
添加数据,并使用MyInheritedWidget.of(context).stream将您的流提供给一个MyInheritedWidget.of(context).stream
这些都只是解释在小部件之间共享数据所需的示例。您可以通读以获取更多信息和更高级的用例。我相信该提供程序是管理颤振应用程序中状态的推荐方法,并在Google IO上展示,并且在
- 谷歌I/O视频
作为我的提供商提供服务…
import 'dart:collection';
import 'package:flutter/material.dart';
class Item {
String name;
num price;
Item(this.name, this.price);
}
class CartModel extends ChangeNotifier {
/// Internal, private state of the cart.
final List<Item> _items = [];
/// An unmodifiable view of the items in the cart.
UnmodifiableListView<Item> get items => UnmodifiableListView(_items);
/// The current total price of all items (assuming all items cost $42).
/// int get totalPrice => _items.length * 42;
/// Adds [item] to cart. This is the only way to modify the cart from outside.
void add(Item item) {
_items.add(item);
// This call tells the widgets that are listening to this model to rebuild.
notifyListeners();
}
}
导入“dart:collection”;
进口“包装:颤振/材料.省道”;
类项目{
字符串名;
数量价格;
项目(此名称、此价格);
}
类CartModel扩展了ChangeNotifier{
///购物车的内部、私有状态。
最终清单_项=[];
///购物车中项目的不可修改视图。
UnmodifiableListView get items=>UnmodifiableListView(\u items);
///所有项目的当前总价(假设所有项目成本为42美元)。
///int get totalPrice=>\u items.length*42;
///将[项目]添加到购物车。这是从外部修改购物车的唯一方法。
无效添加(项目){
_项目。添加(项目);
//此调用告诉正在侦听此模型的小部件重建。
notifyListeners();
}
}
设置对状态的访问*
void main() => runApp(
ChangeNotifierProvider<CartModel>(
child: TabBarDemo(),
builder: (BuildContext context) {
return CartModel();
},
),
);
void main()=>runApp(
变更通知提供者(
子项:TabBarDemo(),
生成器:(BuildContext上下文){
返回CartModel();
},
),
);
从顶层访问状态以在选项卡标题中显示计数
class TabBarDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
var count = Provider.of<CartModel>(context).items.length;
类TabBarDemo扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
var count=Provider.of(context).items.length;
将项目添加到购物车时从第一个选项卡访问状态
RaisedButton(
child: Text("Add Item"),
onPressed: () async {
final form = _formKey.currentState;
form.save();
if (form.validate()) {
Provider.of<CartModel>(context)
.add(new Item(_name, num.parse(_price)));
} else {
print('validate failed');
}
_formKey.currentState.reset();
})
RaisedButton(
子项:文本(“添加项”),
onPressed:()异步{
最终形式=_formKey.currentState;
form.save();
if(form.validate()){
提供者(上下文)
.add(新项目(_name,num.parse(_price));
}否则{
打印(“验证失败”);
}
_formKey.currentState.reset();
})
请参见此处的完整示例:,此代码基于我发现使用好的ole有状态小部件很容易。InputManagement上有一个一流的函数,用于获取数据并构建主页。需要注意的是,InputManagement应该负责任地调用此函数,因为它会重建页面
import 'package:flutter/material.dart';
void main() => runApp(App());
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Tabbar Answer',
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin {
TabController tabController;
List<dynamic> data = [];
@override
void initState() {
super.initState();
tabController = TabController(length: 2, vsync: this);
}
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(title: Text("Tab Delegate")),
body: TabBarView(children: [InputManagement(data: data, delegate: (newData) => setState(() { data = newData; })), InfiniteListView(data: data)], controller: tabController),
bottomNavigationBar: TabBar(controller: tabController, tabs: [Icon(Icons.mail, color: Colors.black), Icon(Icons.view_agenda, color: Colors.black,)])
);
}
class InputManagement extends StatelessWidget {
List<dynamic> data;
void Function(dynamic) delegate;
InputManagement({this.data, this.delegate});
add(dynamic dataItem) {
data.add(dataItem);
delegate(data);
}
@override
Widget build(BuildContext context) => Center(child: FloatingActionButton(onPressed: () => add(data.isEmpty ? 0 : data.last + 1), child: Icon(Icons.add)));
}
class InfiniteListView extends StatelessWidget {
List<dynamic> data = [];
InfiniteListView({this.data});
@override
Widget build(BuildContext context) => ListView.builder(itemBuilder: (context, index) => Container(height: 100, width: MediaQuery.of(context).size.width, alignment: Alignment.center, child: Text(data[index].toString(), style: Theme.of(context).textTheme.title.copyWith(color: Colors.black),)), itemCount: data.length);
}
导入“包装:颤振/材料.省道”;
void main()=>runApp(App());
类应用程序扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
标题:“Tabbar答案”,
主页:主页(),
);
}
}
类主页扩展了StatefulWidget{
@凌驾
_HomePageState createState()=>\u HomePageState();
}
类_HomePageState使用SingleTickerProviderStateMixin扩展状态{
TabController TabController;
列表数据=[];
@凌驾
void initState(){
super.initState();
tabController=tabController(长度:2,vsync:this);
}
@凌驾
小部件构建(构建上下文)=>Scaffold(
appBar:appBar(标题:文本(“制表符委托”),
主体:TabBarView(子项:[输入管理(数据:数据,委托:(newData)=>setState((){data=newData;})),InfiniteListView(数据:数据)],控制器:tabController),
底部导航栏:选项卡栏(控制器:选项卡控制器,选项卡:[图标(Icons.mail,颜色:Colors.black),图标(Icons.view\u议程,颜色:Colors.black,)]
);
}
类InputManagement扩展了无状态小部件{
列出数据;
无效功能(动态)委托;
InputManagement({this.data,this.delegate});
添加(动态数据项){
data.add(数据项);
代表(数据);
}
@凌驾
小部件构建(BuildContext上下文)=>Center(子级:FloatingActionButton(按下时:()=>add(data.isEmpty?0:data.last+1),子级:Icon(Icons.add));
}
类InfiniteListView扩展了无状态小部件{
列表数据=[];
InfiniteListView({this.data});
@凌驾
小部件构建(BuildContext context)=>ListView.builder(itemBuilder:(context,index)=>Container(高度:100,宽度:MediaQuery.of(context).size.width,对齐方式:alignment.center,child:Text(数据[index].toString(),样式:Theme.of(context).textTheme.title.copyWith(颜色:Colors.black)),itemCount:data.length);
}