Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/visual-studio-2010/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Dart 如何防止BuildContext的传递?_Dart_Flutter - Fatal编程技术网

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))
);


 }
}