Flutter bloc – простой пример. Переключение цвета

обновлено: 08.12.2020

  • реализация bloc во flutter без дополнительных библиотек, на потоках (stream) – смотрите пример приложения;
  • базовая библиотека bloc – https://pub.dev/packages/bloc;
  • flutter_bloc – https://pub.dev/packages/flutter_bloc – мощная и наиболее распространенная библиотека во flutter. Эту библиотеку мы и разберем в этом посте.

Полезные ссылки:

Пример переключения цвета на flutter_bloc

Код рассматриваемого проекта можно посмотреть тут.

Мы создаем файл color_bloc.dart в котором мы перечисляем события по нажатию на кнопке: У нас их 2 – event_red и event_green. Эти значения события мы запишем в тип enum {}

Общая схема взаимодействия следующая:


обязательно объявить свой класс (в данном случае ColorBloc), отнаследованный от Bloc
в котором переопределить:
- метод initialState, который должен возвращать state
- метод mapEventToState, принимает событие. метод вызывается, всякий раз, когда добавляется событие. Конвертирует данное событие в новое состояние и возврает его в поток.

В виджете представления:
-BlocProvider
	//виджет, который предоставляет bloc дочерним элементам через _bloc = BlocProvider.of(context)
	в параметре create возвращаем наш объявленный ColorBloc
	
	-- BlocBuilder
		виджет, который содержит в себе контент, который нужно перерисовать.
		в параметре builder указываем функцию, которая принимает контекст и State, в данном случае мы назанчили ему имя - currentColor.
		
	по клику на кнопку _bloc.add(ColorsEvent.event_green) - добавляем событие в наш блок.

color_bloc.dart


import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

enum ColorEvent {event_red, event_green}

//ColocBloc  будет принимать ColorEvent в качестве входного и выходного типа Color
class ColorBloc extends Bloc {
  Color _color = Colors.red;

  @override
  Color get initialState => Colors.red;

  @override
  Stream mapEventToState(ColorEvent event) async* {
    // async* - означает, что мы работаем с потоком
    //бизнес логика приложения
    _color = (event == ColorEvent.event_red) ? Colors.red : Colors.green;
    yield _color; // добавляем значение в выходной поток
    //yield - работает с потоком, добавляет значение в выходной поток. Но в отличие от return - не прекращает работу метода
  }
  
}

main.dart


import 'package:bloc_example/color_bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: BlocProvider(                
        //!!! BlocProvider - виджет,
        //который предоставляет bloc дочерним элементам через  BlocProvider.of(context).
        //может быть предоставлен нескольким виджетам в поддереве.
        create: (context) => ColorBloc(),
        child: MyHomePage(),
      ),
    );
  }
}

class MyHomePage extends StatelessWidget {
  // при использовании flutter_bloc нам не нужно закрывать потоки(в отличие от bloc) и поэтому мы используем StatelessWidget.
  //Данная библиотека делает это автоматически
  @override
  Widget build(BuildContext context) {
    // ignore: close_sinks
    ColorBloc _bloc = BlocProvider.of(context);  //!!!
    return Scaffold(
      appBar: AppBar(
        title: Text('BLoC with flutter_bloc'),
        centerTitle: true,
      ),
      body: Center(
        //на вход: блок ColorBloc. на выход Сolor
        child: BlocBuilder(
          //!!! переписовка контента в ответ на новые состояния
          // bloc - необязательный параметр. для чего???
          builder: (context, currentColor) => AnimatedContainer(   //currentColor !!!!!
            height: 100,
            width: 100,
            color: currentColor,
            duration: Duration(milliseconds: 500),
          ),
        ),
      ),
      floatingActionButton: Row(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          FloatingActionButton(
            backgroundColor: Colors.red,
            onPressed: () {
              _bloc.add(ColorEvent.event_red);          //!!!
            },
          ),
          SizedBox(width: 10),
          FloatingActionButton(
            backgroundColor: Colors.green,
            onPressed: () {
              _bloc.add(ColorEvent.event_green);          //!!!
            },
          ),
        ],
      ),
    );
  }
}

Demo:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *