КОНЦЕПЦИЯ БЛОКА:

  1. Создать мероприятие
  2. Передать событие в BLoc
  3. Состояние возврата блока

Lib /counter_event.dart

Создать мероприятие

abstract class CounterEvent {}
class IncrementEvent extends CounterEvent {}
class DecrementEvent extends CounterEvent {}

Lib /counter_bloc.dart

Передать событие в блок

import 'dart:async'; 
import 'package:bloc_vanilla_tut/counter_event.dart'; 
class CounterBloc {  
int _counter = 0;   
// Cretae Stream Controller for sink data to bloc
final _counterStateController = StreamController<int>();

-------- // Cretae Sink(_inCounter) for input and output(counter)
StreamSink<int> get _inCounter => _counterStateController.sink;  
// For state, exposing only a stream which outputs data  
Stream<int> get counter => _counterStateController.stream; 

// Cretae Second Stream Controller for sink event to bloc  
final _counterEventController = StreamController<CounterEvent>();  
// For events, exposing only a sink which is an input 
Sink<CounterEvent> get counterEventSink =>_counterEventController.sink;
-------- // Cretae Constructor

CounterBloc() {    
// Whenever there is a new event, we want to map it to a new state 
   _counterEventController.stream.listen(_mapEventToState);

 }  
 
--------  // map it to new state
void _mapEventToState(CounterEvent event) 
{    
if (event is IncrementEvent)     
 _counter++;   
 else     
 _counter--;     
_inCounter.add(_counter);  //Add to sink input
 }
--------
void dispose() {                      // dispose StreamController
_counterStateController.close();      // dispose Constructor
 _counterEventController.close(); 
 }}

Lib /main.dart

Состояние возврата блока

import ‘package:bloc_vanilla_tut/counter_bloc.dart’;
import ‘package:bloc_vanilla_tut/counter_event.dart’;
import ‘package:flutter/material.dart’; 
void main() => runApp(MyApp()); 
class MyApp extends StatelessWidget { 
@override Widget build(BuildContext context) {
 return MaterialApp( 
title: ‘Flutter Demo’, 
theme: ThemeData( primarySwatch: Colors.blue, ), 
home: MyHomePage(title: ‘Flutter Demo Home Page’), ); 
}} 

class MyHomePage extends StatefulWidget { 
MyHomePage({Key key, this.title}) : super(key: key); 
final String title; 
@override _MyHomePageState createState() => _MyHomePageState();
} 
class _MyHomePageState extends State<MyHomePage> { 
final _bloc = CounterBloc();
 @override Widget build(BuildContext context) { 
return Scaffold( 
appBar: AppBar( title: Text(widget.title), ), 
body: Center( 
child: 
//StreamBuilder for UI ,without setState
StreamBuilder( 
stream: _bloc.counter,  //output stream (Counetr)
initialData: 0, 
builder: (BuildContext context, AsyncSnapshot<int> snapshot) 
{ 
return Column( 
mainAxisAlignment: MainAxisAlignment.center, 
children: <Widget>[
 Text( ‘You have pushed the button this many times:’, ), 
Text( ‘${snapshot.data}’, 
style: Theme.of(context).textTheme.display1, ), ], ); 
}, ), ),
 floatingActionButton: Row( 
mainAxisAlignment: MainAxisAlignment.end, 
children: <Widget>[
 FloatingActionButton( 
onPressed: () => _bloc.counterEventSink.add(IncrementEvent()), tooltip: ‘Increment’, child: Icon(Icons.add), ),
 SizedBox(width: 10), 
FloatingActionButton( 
onPressed: () => _bloc.counterEventSink.add(DecrementEvent()), tooltip: ‘Decrement’, child: Icon(Icons.remove), ), ],
 ), ); }

 @override void dispose() {  //Dispose Bloc
super.dispose();
 _bloc.dispose(); 
}}

Мои статьи бесплатны, но вы знаете, что можете нажать кнопку хлопка 50 раз? Чем выше вы поднимаетесь, тем больше это мотивирует меня писать для вас больше!