Dart 如何防止BuildContext的传递?
目前,我从Dart 如何防止BuildContext的传递?,dart,flutter,Dart,Flutter,目前,我从主屏幕中的build方法获取BuildContext,然后我必须将其传递到\u gridslaver,然后再传递到\u storeCard 如何编写代码,使我不需要传递上下文 也许我可以创建一个名为\u StoreCard的新的私有无状态小部件,它将有自己的构建方法,从而有自己的构建上下文 class HomeScreen extends StatelessWidget { HomeScreen({Key key}) : super(key: key); @override
主屏幕
中的build
方法获取BuildContext
,然后我必须将其传递到\u gridslaver
,然后再传递到\u storeCard
如何编写代码,使我不需要传递上下文
也许我可以创建一个名为\u StoreCard
的新的私有无状态小部件
,它将有自己的构建
方法,从而有自己的构建上下文
class HomeScreen extends StatelessWidget {
HomeScreen({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return StoreConnector<AppState, List<MyStore.Store>>(
converter: (Store<AppState> store) => store.state.home.stores,
builder: (BuildContext context, List<MyStore.Store> stores) =>
CustomScrollView(slivers: <Widget>[_gridSliver(stores, context)]));
}
Widget _gridSliver(stores, context) {
return SliverGrid(
delegate: SliverChildListDelegate(List<Widget>.from(stores.map(_storeCard, context))));
}
Widget _storeCard(MyStore.Store store, BuildContext context) {
return InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (_) => StoreScreen(storeId: store.id)),
);
},
child: Container(child: Text(store.name))
);
}
}
要获得新的
BuildContext
,您有两个主要解决方案:
- 将部分子树提取到新的小部件中,通常是
。然后使用无状态小部件
方法中的build
BuildContext
- 使用
小部件,它基本上是一个可重用的小部件,用于获取Builder
:BuildContext
@override
Widget build(BuildContext context) {
return Builder(
builder: (context) {
// do something with this new context
},
);
}
您必须使用一个使用继承小部件的Bloc模式,但仍然必须以更直接的方式传递上下文。我推荐使用Stephen Grider,来了解整个过程是如何工作的。他在他的教程中解释了如何把所有的东西放在一起,但我不能把你和这个联系起来,因为那将是广告 其思想是,首先创建一个包含逻辑的文件Bloc.dart,然后在Provider.dart中创建一个称为Provider的文件 Provider.dart:
class Provider extends InheritedWidget {
final bloc = Bloc();
Provider({Key key, Widget child}) : super(key: key, child: child);
bool updateShouldNotify(_) => true;
static Bloc of(BuildContext context) {
return (context.inheritFromWidgetOfExactType(Provider) as Provider).bloc;
}
}
在包含材质应用程序的文件中,使用提供程序包装材质应用程序:
Widget build(BuildContext context) {
return Provider(
child: MaterialApp(
然后,在三个小部件中的每一个类中使用提供者
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final bloc = Provider.of(context); // this is where you insert the provider
return StoreConnector<AppState, List<MyStore.Store>>(
converter: (Store<AppState> store) => store.state.home.stores,
builder: (BuildContext context, List<MyStore.Store> stores) =>
CustomScrollView(slivers: <Widget>[_gridSliver(stores, context)]));
}
Widget _gridSliver(stores) {
final bloc = Provider.of(context);
return SliverGrid(
delegate: SliverChildListDelegate(List<Widget>.from(stores.map(_storeCard, context))));
}
Widget _storeCard(MyStore.Store store) {
final bloc = Provider.of(context);
return InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (_) => StoreScreen(storeId: store.id)),
);
},
child: Container(child: Text(store.name))
);
}
}
类主屏幕扩展小部件{
@凌驾
小部件构建(构建上下文){
final bloc=Provider.of(context);//这是插入提供程序的地方
返回存储连接器(
转换器:(商店)=>Store.state.home.stores,
生成器:(BuildContext上下文,列表存储)=>
CustomScrollView(片段:[[u GridSlaver(存储,上下文)]);
}
Widget\u gridSliver(商店){
final bloc=Provider.of(上下文);
回程缝栅(
委托:SliverChildListDelegate(List.from(stores.map(_storeCard,context)));
}
Widget\u存储卡(MyStore.Store){
final bloc=Provider.of(上下文);
回墨槽(
onTap:(){
导航器。推(
上下文
MaterialPackageRoute(生成器:()=>StoreScreen(storeId:store.id)),
);
},
子:容器(子:文本(store.name))
);
}
}
我是一个彻头彻尾的蠢货,什么都拿不定,但这就是我要用的。希望有帮助。对于无状态小部件,最好将其传递给其他小部件,或者将方法迁移到它们自己的小部件上。我喜欢这个解决方案。这和使用BLoC架构(比如MVC)是一样的吗?否则,我看不到它在其他任何地方使用。我真希望我能做这样的事情,但是这个解决方案不是框架建议的解决方案。我宁愿编写难看的代码,也不愿有一些以后可能会忘记的magcial解决方案。如果我需要一个不构建子树的函数中的BuildContext实例,该怎么办?例如,我想获得一个changenotifier来对其执行某种操作。把这个背景传给别人有点难看。。。
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final bloc = Provider.of(context); // this is where you insert the provider
return StoreConnector<AppState, List<MyStore.Store>>(
converter: (Store<AppState> store) => store.state.home.stores,
builder: (BuildContext context, List<MyStore.Store> stores) =>
CustomScrollView(slivers: <Widget>[_gridSliver(stores, context)]));
}
Widget _gridSliver(stores) {
final bloc = Provider.of(context);
return SliverGrid(
delegate: SliverChildListDelegate(List<Widget>.from(stores.map(_storeCard, context))));
}
Widget _storeCard(MyStore.Store store) {
final bloc = Provider.of(context);
return InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (_) => StoreScreen(storeId: store.id)),
);
},
child: Container(child: Text(store.name))
);
}
}