如何防止传递 BuildContext?

psy*_*ite 4 dart flutter

目前我BuildContextbuild方法中获取HomeScreen,然后我必须将它传递给_gridSliver然后传递给_storeCard.

如何编写代码以便我不需要向下传递上下文?

也许我可以创建一个新的私有StatelessWidget调用_StoreCard,它将拥有自己的build方法,从而拥有自己的方法BuildContext

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))
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

这个问题的另一个例子是我在子函数上导航。

@override
Widget build(BuildContext context) {
  return Column(
    children: [
      WhiteButton(text: "Login with Facebook", onPressed: _loginWithFacebook),
      WhiteButton(text: "Login with Google", onPressed: _loginWithGoogle),
    ])
  )
}

_loginWithFacebook(context) async {
    ...
    var user = User.fromFacebook(result.accessToken.token, json.decode(graphResponse.body));
    await _login(user, context);
  }
}

_loginWithGoogle(context) async {
    ...
  GoogleSignInAccount googleUser = await _googleSignIn.signIn();
  await _login(User.fromGoogle(googleUser), context);
}

_login(user, context) async {
  var fetchedUser = await MeService.getUser(user);
  if (fetchedUser != null) {
    loginSuccess(fetchedUser);
    Navigator.popUntil(context, ModalRoute.withName(MainRoutes.root));
  } else {
    Navigator.push(
      context,
      MaterialPageRoute(builder: (_) => RegisterScreen(user: user)),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

Rém*_*let 5

要获得新的BuildContext,您有两个主要解决方案:

  • 将子树的一部分提取到一个新的小部件中,通常是StatelessWidget. 然后用它BuildContextbuild方法

  • 使用Builder小部件,它基本上是一个可重用的小部件,用于获取BuildContext

例子:

 @override
 Widget build(BuildContext context) {
  return Builder(
    builder: (context) {
      // do something with this new context
    },
  );
}
Run Code Online (Sandbox Code Playgroud)