#flutter #bloc
#трепетание #блок
Вопрос:
в следующем тестовом коде я пытаюсь отправить событие в TestBloc при нажатии кнопки на панели приложений. Я переместил блокбастер наружу вокруг эшафота. Но когда вызывается метод _reloadData, появляется следующая ошибка
"BlocProvider.of() called with a context that does not contain a Bloc/Cubit of type TestBloc"
Код
class _TestPageState extends State<TestPage> with UiPresenter {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => sl<TestBloc>()..add(GetDataEvent()),
child: Scaffold(
appBar: AppBar(
title: AppBarTitleWidget(
title: 'Test',
onRefreshPressed: () => _reloadData(context),
)),
drawer: MainMenuDrawer(),
body: ContentContainer(
header: Text(
'Test',
style: Theme.of(context).textTheme.headline1,
),
child: _buildBody(context),
),
),
);
}
_reloadData(BuildContext context) {
BlocProvider.of<TestBloc>(context).add(GetDataEvent());
}
Ответ №1:
Вы можете скопировать вставить запустить полный код ниже
Я использую следующий полный код для имитации этого случая
Вы можете обернуть AppBarTitleWidget
с помощью Builder
фрагмент кода
appBar: AppBar(title: Builder(builder: (BuildContext context) {
return AppBarTitleWidget(
title: "Test",
onRefreshPressed: () => _reloadData(context),
);
}))
рабочая демонстрация
полный код
import 'package:bloc/bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class TestBloc extends Cubit<int> {
/// {@macro counter_cubit}
TestBloc() : super(0);
/// Add 1 to the current state.
void GetDataEvent() => emit(state 1);
/// Subtract 1 from the current state.
void decrement() => emit(state - 1);
}
/*class CounterPage extends StatelessWidget {
/// {@macro counter_page}
const CounterPage({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => CounterCubit(),
child: CounterView(),
);
}
}*/
/// {@template counter_observer}
/// [BlocObserver] for the counter application which
/// observes all [Cubit] state changes.
/// {@endtemplate}
class CounterObserver extends BlocObserver {
@override
void onChange(Cubit cubit, Change change) {
print('${cubit.runtimeType} $change');
super.onChange(cubit, change);
}
}
void main() {
Bloc.observer = CounterObserver();
runApp(CounterApp());
}
class CounterApp extends MaterialApp {
/// {@macro counter_app}
CounterApp({Key key}) : super(key: key, home: TestPage());
}
_reloadData(BuildContext context) {
BlocProvider.of<TestBloc>(context).GetDataEvent();
}
class TestPage extends StatefulWidget {
@override
_TestPageState createState() => _TestPageState();
}
class _TestPageState extends State<TestPage> {
@override
Widget build(BuildContext context) {
final textTheme = Theme.of(context).textTheme;
return BlocProvider(
create: (_) => TestBloc(),
child: Scaffold(
appBar: AppBar(title: Builder(builder: (BuildContext context) {
return AppBarTitleWidget(
title: "Test",
onRefreshPressed: () => _reloadData(context),
);
})),
body: Center(
child: BlocBuilder<TestBloc, int>(
builder: (context, state) {
return Text('$state', style: textTheme.headline2);
},
),
),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
FloatingActionButton(
key: const Key('counterView_increment_floatingActionButton'),
child: const Icon(Icons.add),
onPressed: () => context.read<TestBloc>().GetDataEvent(),
),
const SizedBox(height: 8),
FloatingActionButton(
key: const Key('counterView_decrement_floatingActionButton'),
child: const Icon(Icons.remove),
onPressed: () => context.read<TestBloc>().decrement(),
),
],
),
),
);
}
}
class AppBarTitleWidget extends StatelessWidget {
final String title;
final VoidCallback onRefreshPressed;
const AppBarTitleWidget({
Key key,
this.title,
this.onRefreshPressed,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
onRefreshPressed();
},
child: Text(title));
}
}