Эй, разработчики флаттера!

Сегодня мы углубимся в мир Flutter и его управление состоянием.

В частности, мы будем изучать шаблон BLoC. Если вы какое-то время были в сообществе Flutter, вы, вероятно, слышали о BLoC.

Но если вы новичок или вам нужно освежить знания, это руководство для вас.

1. Что такое БЛОК?

BLoC означает БизнесЛогическийКомпоненткомпонент.

Это шаблон проектирования, который отделяет уровень представления от бизнес-логики в приложении Flutter.

Основная идея — управлять состоянием и сделать наши приложения более масштабируемыми и удобными в обслуживании.

2. Почему BLoC?

Flutter предлагает множество решений по управлению состоянием, но BLoC выделяется по нескольким причинам:

  • Разделение задач. BLoC гарантирует, что пользовательский интерфейс и бизнес-логика остаются разделенными.
  • Реактивность: BLoC использует потоки, что делает его по своей сути реактивным.
  • Тестируемость. Благодаря своей архитектуре тестирование становится проще простого.

3. Настройка BLoC

Прежде чем углубиться в код, давайте настроим нашу среду:

1) Создайте новый проект Flutter с нулевой безопасностью:

flutter create --org com.example bloc_example

2) Добавьте необходимые пакеты в свой pubspec.yaml:

dependencies:
  flutter:
    sdk: flutter
  flutter_bloc: ^7.0.0

3) Запустите flutter pub get, чтобы установить пакеты.

4. Основы БЛОК

По своей сути BLoC использует два основных компонента: События и Состояния.

  • События: это входные данные для BLoC. Например, нажатие кнопки.
  • Состояния: выходные данные или результат обработки события.

5. Создание нашего первого блока управления

Давайте создадим простое приложение-счетчик с использованием BLoC.

1) Определить события:

abstract class CounterEvent {}

class IncrementEvent extends CounterEvent {}

class DecrementEvent extends CounterEvent {}

2) Определить состояния:

abstract class CounterState {
  final int value;
  CounterState(this.value);
}

class InitialState extends CounterState {
  InitialState() : super(0);
}
class UpdatedState extends CounterState {
  UpdatedState(int value) : super(value);
}

3) Внедрить BLoC:

class CounterBloc extends Bloc<CounterEvent, CounterState> {
  CounterBloc() : super(InitialState());
  @override
  Stream<CounterState> mapEventToState(CounterEvent event) async* {
    if (event is IncrementEvent) {
      yield UpdatedState(state.value + 1);
    } else if (event is DecrementEvent) {
      yield UpdatedState(state.value - 1);
    }
  }
}

4) Интеграция с пользовательским интерфейсом:

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: BlocProvider(
        create: (context) => CounterBloc(),
        child: CounterPage(),
      ),
    );
  }
}
class CounterPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final bloc = BlocProvider.of<CounterBloc>(context);
    return Scaffold(
      appBar: AppBar(title: Text('Counter App')),
      body: BlocBuilder<CounterBloc, CounterState>(
        builder: (context, state) {
          return Center(
            child: Text('Count: ${state.value}'),
          );
        },
      ),
      floatingActionButton: Column(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          FloatingActionButton(
            onPressed: () => bloc.add(IncrementEvent()),
            child: Icon(Icons.add),
          ),
          SizedBox(height: 10),
          FloatingActionButton(
            onPressed: () => bloc.add(DecrementEvent()),
            child: Icon(Icons.remove),
          ),
        ],
      ),
    );
  }
}

6) Тестирование блока управления

Одним из преимуществ BLoC является его тестируемость. Вот простой тест для нашего CounterBloc:

void main() {
  group('CounterBloc', () {
    late CounterBloc bloc;
    setUp(() {
      bloc = CounterBloc();
    });
    test('initial state is 0', () {
      expect(bloc.state.value, 0);
    });
    blocTest<CounterBloc, CounterState>(
      'emits [1] when IncrementEvent is added',
      build: () => bloc,
      act: (bloc) => bloc.add(IncrementEvent()),
      expect: () => [UpdatedState(1)],
    );
    blocTest<CounterBloc, CounterState>(
      'emits [-1] when DecrementEvent is added',
      build: () => bloc,
      act: (bloc) => bloc.add(DecrementEvent()),
      expect: () => [UpdatedState(-1)],
    );
  });
}

7) Заключение

Ключом к овладению BLoC (или любым другим инструментом) является последовательная практика и практическое применение. Итак, приступайте к сборке и удачи в программировании!

Я надеюсь, что это руководство дает четкое понимание того, как использовать BLoC во Flutter. Если у вас есть какие-либо вопросы или отзывы, не стесняйтесь оставлять их в комментариях ниже. Приятного кодирования!

Кроме того, это руководство представляет собой базовое введение в BLoC во Flutter. Есть и более сложные функции и нюансы, которые вы сможете изучить по мере знакомства с шаблоном :)

Прежде чем мы уйдем…

Эй, спасибо, что остаешься рядом! Если этот пост вас зацепил, представьте, что будет дальше.

Я запускаю канал на YouTube, и поверьте мне, вы не захотите его пропустить. Посмотрите и, может быть, даже нажмите кнопку подписки?

Нажмите, чтобы подписаться.

Пока мы не встретимся снова, кодируйте и сохраняйте любопытство!

Есть сомнения или хотите пообщаться? Реагируйте на меня в twitter или linkedin.