flutter_block: BlockProvider против RepositoryProvider
Я хочу пояснить BlockProvider
а также RepositoryProvider
. Судя по официальной справке по API, они предоставляют ту же функциональность - они предоставляют экземпляр объекта его дочерним виджетам.
Однако, судя по названиям, наверное BlockProvider
следует использовать для Bloc
только объекты, и RepositoryProvider
для всего остального. Это правильно?
2 ответа
RepositoryProvider действует как шаблон репозитория.
Это поставщик данных предоставляет данные для Bloc, поэтому Bloc не нужно знать, что данные поступают из облака или sqflite или...
И выполните слияние / фильтр, см. Официальный пример ниже
В следующем примере LoginForm
репозиторий является частью Bloc, и вы можете использовать_userRepository.login
class LoginFormBloc extends FormBloc<String, String> {
final emailField = TextFieldBloc(validators: [Validators.email]);
final passwordField = TextFieldBloc();
final UserRepository _userRepository;
LoginFormBloc(this._userRepository);
@override
List<FieldBloc> get fieldBlocs => [emailField, passwordField];
@override
Stream<FormBlocState<String, String>> onSubmitting() async* {
try {
_userRepository.login(
email: emailField.value,
password: passwordField.value,
);
yield currentState.toSuccess();
} catch (e) {
yield currentState.toFailure();
}
}
}
Вы можете внедрить свой репозиторий в
фрагмент кода Bloc
class LoginForm extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider<LoginFormBloc>(
builder: (context) =>
LoginFormBloc(RepositoryProvider.of<UserRepository>(context)),
child: Builder(
builder: (context) {
final formBloc = BlocProvider.of<LoginFormBloc>(context);
return Scaffold(
appBar: AppBar(title: Text('Simple login')),
body: FormBlocListener<LoginFormBloc, String, String>(
onSubmitting: (context, state) => LoadingDialog.show(context),
onSuccess: (context, state) {
LoadingDialog.hide(context);
Navigator.of(context).pushReplacementNamed('success');
},
onFailure: (context, state) {
LoadingDialog.hide(context);
Notifications.showSnackBarWithError(
context, state.failureResponse);
},
вы можете ссылаться на https://flutterawesome.com/create-beautiful-forms-in-flutter/
для официального примера https://bloclibrary.dev/
Уровень блока может зависеть от одного или нескольких репозиториев для получения данных, необходимых для создания состояния приложения.
class Repository {
final DataProviderA dataProviderA;
final DataProviderB dataProviderB;
Future<Data> getAllDataThatMeetsRequirements() async {
final RawDataA dataSetA = await dataProviderA.readData();
final RawDataB dataSetB = await dataProviderB.readData();
final Data filteredData = _filterData(dataSetA, dataSetB);
return filteredData;
}
}
class BusinessLogicComponent extends Bloc<MyEvent, MyState> {
final Repository repository;
Stream mapEventToState(event) async* {
if (event is AppStarted) {
try {
final data = await repository.getAllDataThatMeetsRequirements();
yield Success(data);
} catch (error) {
yield Failure(error);
}
}
}
}
Простой ответ
То же, что и BlocProvider.
BlockProvider предоставляет блок своим дочерним элементам через BlockProvider.of(context). В большинстве случаев разработчики создают новый BlocProvider, который становится доступным для остальной части поддерева.
Теперь переходим к RepositoryProvider
RepositoryProvider предоставляет репозиторий своим потомкам через RepositoryProvider.of (context). Когда разработчики создают новый RepositoryProvider, который становится доступным для остальной части поддерева.