Skip to content

Latest commit

 

History

History
164 lines (121 loc) · 4.75 KB

recipes_flutter_snackbar.md

File metadata and controls

164 lines (121 loc) · 4.75 KB

Up

Recipes: Show SnakeBar with BlocListener

원문: Bloc / Recipes / Flutter / Show SnackBar

한국어로 번역은 현재 진행중입니다.

In this recipe, we're going to take a look at how to use BlocListener to show a SnackBar in response to a state change in a bloc.

demo

Let's build a basic DataBloc which will handle DataEvents and output DataStates.

For simplicity, our DataBloc will only respond to a single DataEvent called FetchData.

import 'package:meta/meta.dart';

@immutable
abstract class DataEvent {}

class FetchData extends DataEvent {}

Our DataBloc can have one of three different DataStates:

  • Initial - the initial state before any events are dispatched
  • Loading - the state of the bloc while it is asynchronously "fetching data"
  • Success - the state of the bloc when it has successfully "fetched data"
import 'package:meta/meta.dart';

@immutable
abstract class DataState {}

class Initial extends DataState {}

class Loading extends DataState {}

class Success extends DataState {}

Our DataBloc should look something like this:

import 'package:bloc/bloc.dart';

class DataBloc extends Bloc<DataEvent, DataState> {
  @override
  DataState get initialState => Initial();

  @override
  Stream<DataState> mapEventToState(
    DataEvent event,
  ) async* {
    if (event is FetchData) {
      yield Loading();
      await Future.delayed(Duration(seconds: 2));
      yield Success();
    }
  }
}

Note: We're using Future.delayed to simulate latency.

Now let's take a look at how to hook up our DataBloc to a widget and show a SnackBar in response to a success state.

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      bloc: DataBloc(),
      child: MaterialApp(
        home: Home(),
      ),
    );
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Home')),
      body: BlocListener(
        bloc: BlocProvider.of<DataBloc>(context),
        listener: (BuildContext context, DataState state) {
          if (state is Success) {
            Scaffold.of(context).showSnackBar(
              SnackBar(
                backgroundColor: Colors.green,
                content: Text('Success'),
              ),
            );
          }
        },
        child: BlocBuilder(
          bloc: BlocProvider.of<DataBloc>(context),
          builder: (BuildContext context, DataState state) {
            if (state is Initial) {
              return Center(child: Text('Press the Button'));
            }
            if (state is Loading) {
              return Center(child: CircularProgressIndicator());
            }
            if (state is Success) {
              return Center(child: Text('Success'));
            }
          },
        ),
      ),
      floatingActionButton: Column(
        crossAxisAlignment: CrossAxisAlignment.end,
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          FloatingActionButton(
            child: Icon(Icons.play_arrow),
            onPressed: () {
              BlocProvider.of<DataBloc>(context).dispatch(FetchData());
            },
          ),
        ],
      ),
    );
  }
}

We use the BlocListener widget in order to DO THINGS in response to state changes in our DataBloc.

We use the BlocBuilder widget in order to RENDER WIDGETS in response to state changes in our DataBloc.

We should NEVER "do things" in response to state changes in the builder method of BlocBuilder because that method can be called many times by the Flutter framework. The builder method should be a pure function that just returns a widget in response to the state of the bloc.

The full source for this recipe can be found here.


이전: Github Search

다음: Navigation