Почему BlocBuilder никогда не вызывается, если blo c не установлен явно - PullRequest
0 голосов
/ 24 апреля 2020

Это пример приложения счетчика флаттера. Я создаю экземпляр счетчика с помощью Blo c следующим образом:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: Counter(CounterBloc()),
    );
  }
}

Этот код ниже работает нормально. Событие отправляется и вызывается метод "builder".

class Counter extends StatelessWidget {
  final Bloc bloc;

  const Counter(this.bloc, {Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocProvider<CounterBloc>(
      create: (context) => bloc,
      child: CounterPage(),
    );
  }
}

class CounterPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: BlocBuilder<CounterBloc, int>(
        builder: (context, count) => CountView(count),
      ),
      floatingActionButton: AddButton(
          action: () => BlocProvider.of<CounterBloc>(context)
              .add(CounterEvent.increment)),
    );
  }
}

Код ниже не работает. Событие отправляется, но конструктор никогда не вызывается.

class Counter extends StatelessWidget {
  final Bloc bloc;

  const Counter(this.bloc, {Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocProvider<CounterBloc>(
      create: (context) => bloc,
      child: Scaffold(
        body: BlocBuilder<CounterBloc, int>(
          builder: (context, count) => CountView(count),
        ),
        floatingActionButton: AddButton(
            action: () => BlocProvider.of<CounterBloc>(context)
                .add(CounterEvent.increment)),
      ),
    );
  }
}

Я обнаружил, что могу установить свойство "blo c" в BlocBuilder, но я ожидаю, что в этом нет необходимости. Почему разница в поведении?

1 Ответ

0 голосов
/ 24 апреля 2020

Я полагаю, что CounterEvent.increment из нерабочего фрагмента не будет отправлен и вместо этого выдаст ошибку BlocProvider.of() called with a context ..., потому что вы используете тот же context, где вы указали bloc.

Это код работает, потому что это новый context после BlocProvider

class Counter extends StatelessWidget {
  final Bloc bloc;

  const Counter(this.bloc, {Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocProvider<CounterBloc>(
      create: (context) => bloc,
      child: Builder(
        builder: (context) => Scaffold(
          body: BlocBuilder<CounterBloc, int>(
            builder: (context, count) => CountView(count),
          ),
          floatingActionButton: AddButton(
            action: () => BlocProvider.of<CounterBloc>(context)
                .add(CounterEvent.increment),
          ),
        ),
      ),
    );
  }
}

Этот код также работает, потому что мы явно используем экземпляр bloc из конструктора вместо вызова BlocProvider.of() и использования предоставленного экземпляра bloc через BlocProvider.

class Counter extends StatelessWidget {
  final Bloc bloc;

  const Counter(this.bloc, {Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocProvider<CounterBloc>(
      create: (context) => bloc,
      child: Scaffold(
        body: BlocBuilder<CounterBloc, int>(
          bloc: bloc,
          builder: (context, count) => CountView(count),
        ),
        floatingActionButton: AddButton(
          action: () => bloc.add(CounterEvent.increment),
        ),
      ),
    );
  }
}

Оба приведенных выше фрагмента будут работать, но это не совсем "правильный" способ.

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: Counter(
        CounterBloc(), // <=() You need a work around to dispose this instance
      ),
    );
  }
}
...