Контекст не содержит блоков

#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));
  }
}