我有一个Flutter应用,其中包含2个标签:一个标签用于管理和接收连续的数据流,另一个标签显示输入的数据。
如何将数据从第一个标签传递到第二个标签?我看到的大多数帖子都是关于在父子之间传递数据,而不是在子与子之间传递数据。
我会使用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(),
],
),
);
}
答案 0 :(得分:0)
在这种情况下,建议使用InheritedWidget
。
documentation for InheritedWidget
非常全面,其中包括video from the Flutter team。
首先,您可能想要创建一个类,其中包含要共享的数据。
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
将流提供给StreamBuilder
。
这些都是示例,用以解释在小部件之间共享数据所需的内容。您可以阅读documentation,以了解更多信息和更高级的用例。
答案 1 :(得分:0)
我相信Provider是在Flutter Application中管理状态的推荐方法,并且已在Google IO上提供,并且在Flutter Documentation on State Management
中处于状态管理堆栈的顶部作为我的提供者的服务...
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();
}
}
设置对州的访问权限*
void main() => runApp(
ChangeNotifierProvider<CartModel>(
child: TabBarDemo(),
builder: (BuildContext context) {
return CartModel();
},
),
);
从顶层访问状态以在标签标题中显示计数
class TabBarDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
var count = Provider.of<CartModel>(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();
})
在此处查看完整的示例:https://github.com/aaronksaunders/flutter_simple_tabs,此代码基于Flutter Documentation Example
答案 2 :(得分:0)
我发现使用状态良好的小部件很容易。 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);
}