我正在使用flutter_bloc库来构建我的应用程序。除了BlocProvider之外,我还使用存储库提供程序,因为我将在整个应用程序中广泛使用特定的存储库。但是我在上下文方面有一个问题。以下是我的代码段:
主镖
void main() async { ....... appRepository _appRepository = AppRepository(); SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]) .then((_) { runApp( BlocProvider( builder: (context) => AuthenticationBloc(appRepository: _appRepository)..dispatch(AppStarted()), child: App(appRepository: _appRepository,), ), ); }); } class App extends StatelessWidget { ............ @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: BlocBuilder<AuthenticationBloc, AuthenticationState>( builder: (BuildContext context, AuthenticationState state) { ..... if (state is AuthenticationUnauthenticated) { return SafeArea( top: false, bottom: false, child: RepositoryProvider( builder: (context) => _appRepository, child: LoginPage(firebaseMessaging: _firebaseMessaging), ), ); } ...... }, ), ); } }
在登录表单中找到注册按钮:
register_button.dart
class RegisterButton extends StatelessWidget { final FirebaseMessaging _firebaseMessaging; RegisterButton({ Key key, @required FirebaseMessaging firebaseMessaging, }) : assert(firebaseMessaging != null), _firebaseMessaging = firebaseMessaging, super(key: key); @override Widget build(BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text("Don't have an account?", style: TextStyle(color: Colors.black)), SizedBox(width: 4.0), GestureDetector( child: Text("Register here!", style: TextStyle( color: Color(0xFF585B8D), fontWeight: FontWeight.w500)), onTap: () { Navigator.of(context).push( MaterialPageRoute(builder: (context) { return RegisterPage( firebaseMessaging: _firebaseMessaging, ); }), ); }, ) ], ); }
register_page.dart
class RegisterPage extends StatelessWidget { final FirebaseMessaging _firebaseMessaging; RegisterPage({ Key key, @required FirebaseMessaging firebaseMessaging, }) : assert(firebaseMessaging != null), _firebaseMessaging = firebaseMessaging, super(key: key); @override Widget build(BuildContext context) { return Scaffold( body: BlocProvider( builder: (context) => RegisterBloc( appRepository: RepositoryProvider.of<AppRepository>(context), firebaseMessaging: _firebaseMessaging, ), child: RegisterForm(), ), ); } }
题:
单击登录表单上的注册按钮时,出现以下错误:
No ancestor could be found starting from the context that was passed to RepositoryProvider.of<AppRepository>(). This can happen if: 1. The context you used comes from a widget above the RepositoryProvider. 2. You used MultiRepositoryProvider and didn't explicity provide the RepositoryProvider types. Good: RepositoryProvider<AppRepository>(builder: (context) => AppRepository()) Bad: RepositoryProvider(builder: (context) => AppRepository()). The context used was: BlocProvider<RegisterBloc>(dirty, state: _DelegateWidgetState#a87b2(lifecycle state: created))
为什么会出现此错误?如果在主函数中将存储库提供程序作为blocprovider的子级,将应用程序作为子存储库提供程序,然后在App()中删除单个存储库提供程序,则似乎可以解决此问题。我猜问题出在按下按钮上的材料页面路线。我认为我不了解上下文或提供程序在Flutter中的工作原理。我以为提供商会为存储库/块查找小部件树,推动路由是否会破坏这种连续性?
当您使用Navigator.of(context).push或Navigator.of(context).pushNamed推小部件不小部件的孩子该呼叫Navigator.of(context).push或Navigator.of(context).pushNamed,这个小部件是最接近实例的孩子Navigator包围给context,你的情况Navigator是由创建MaterialApp,因此,如果您想提供Repository或Bloc不同的是routes,Provider必须是的父母Navigator,在你的情况下必须是的父母MaterialApp。
Navigator.of(context).push
Navigator.of(context).pushNamed
Navigator
context
MaterialApp
Repository
Bloc
routes
Provider