Я использую библиотеку flutter_bloc для разработки своего приложения.В дополнение к BlocProvider я использую Repository Provider, так как я буду широко использовать определенный репозиторий в своем приложении.Но у меня проблема с контекстом.Ниже мой код:
main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
BlocSupervisor.delegate = SimpleBlocDelegate();
PrefsRepository.prefs = await SharedPreferences.getInstance();
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 {
final AppRepository _appRepository;
App({AppRepository appRepository})
: assert(appRepository != null),
_appRepository = appRepository;
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: BlocBuilder<AuthenticationBloc, AuthenticationState>(
builder: (BuildContext context, AuthenticationState state) {
if (state is AuthenticationAuthenticated) {
....
}
if (state is AuthenticationUnauthenticated) {
return SafeArea(
top: false,
bottom: false,
child: RepositoryProvider(
builder: (context) => _appRepository,
child: LoginPage(firebaseMessaging: _firebaseMessaging),
),
);
}
if (state is AuthenticationLoading) {
.....
}
},
),
);
}
}
login_page.dart
class LoginPage extends StatelessWidget {
final FirebaseMessaging _firebaseMessaging;
LoginPage({
Key key,
@required FirebaseMessaging firebaseMessaging,
}) : assert(firebaseMessaging != null),
_firebaseMessaging = firebaseMessaging,
super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: BlocProvider(
builder: (context) => LoginBloc(
appRepository: RepositoryProvider.of<AppRepository>(context),
firebaseMessaging: _firebaseMessaging,
),
child: LoginForm(
firebaseMessaging: _firebaseMessaging,
),
),
);
}
}
login_form.dart
class LoginForm extends StatefulWidget {
final FirebaseMessaging _firebaseMessaging;
LoginForm({
Key key,
@required FirebaseMessaging firebaseMessaging,
}) : assert(firebaseMessaging != null),
_firebaseMessaging = firebaseMessaging,
super(key: key);
@override
State<LoginForm> createState() => _LoginFormState();
}
class _LoginFormState extends State<LoginForm> {
.....
@override
Widget build(BuildContext context) {
double _width = MediaQuery.of(context).size.width;
EdgeInsets _contentPadding = EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0);
return BlocListener(
bloc: _loginBloc,
listener: (BuildContext context, LoginState state) {
.....
},
child: BlocBuilder<LoginBloc, LoginState>(
builder: (
BuildContext context,
LoginState state,
) {
return ...
....
RegisterButton(
firebaseMessaging: widget._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.Я думал, что провайдер будет искать дерево виджетов для репозитория / блока. Разве пробивание маршрута как-то нарушает эту непрерывность?