Flutter

Flutter状态管理:BLoC(Business Logic

2021-01-22  本文已影响0人  青叶小小

一、前言

占位

二、什么是BLoC?

BLoC只是一个概念(Reactive Programming,响应式编程),它是基于“dart:async”中的Stream、StreamController来实现的。


BLOC.png

BLoC能够允许我们完美的分离业务逻辑!再也不用考虑什么时候需要刷新屏幕了,一切交给StreamBuilder和BLoC! BLoC由来自Google的两位工程师 Paolo Soares和Cong Hui设计,并在2018年DartConf期间(2018年1月23日至24日)首次展示!


BLoC.png

三、BLoC创建方式

创建方式有三种:

3.1、全局单例模式

全局单例模式并不推荐,原因在于:持久占用Stream而不会释放(dispose)

3.1.1、新建Model

// CountBloc.dart
import 'dart:async';

class CountBloc {
  int _count = 0;
  StreamController<int> _controller;

  Stream<int> get count => _controller.stream;

  CountBloc() {
    _count = 0;
    _controller = StreamController.broadcast();
  }

  void increment() {
    _controller.sink.add(++_count);
  }

  void dispose() {
    _controller.close();
  }
}

CountBloc bloc = CountBloc();

3.1.2、新建两个页面(BlocPage和BlocPageTwo)

// BlocPage.dart
import 'package:flutter/material.dart';
import 'package:stateresearch/bloc/models/CountBloc.dart';
import 'package:stateresearch/pages/BlocPageTwo.dart';

class BlocPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return _body(context);
  }

  Widget _body(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("BlocPage"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('You have pushed the button this many times:'),
            StreamBuilder(
                stream: bloc.count,
                initialData: 0,
                builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
                  return Text("${snapshot.data}");
                }),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) {
            return BlocPageTwo();
          }));
        },
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}
// BlocPageTwo.dart
import 'package:flutter/material.dart';
import 'package:stateresearch/bloc/models/CountBloc.dart';

class BlocPageTwo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return _body(context);
  }

  Widget _body(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("BlocPageTwo"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('You have pushed the button this many times:'),
            StreamBuilder(
                stream: bloc.count,
                initialData: 0,
                builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
                  return Text("${snapshot.data}");
                }),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          bloc.increment();
        },
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

3.1.3、修改main文件

import 'package:flutter/material.dart';
import 'package:stateresearch/pages/BlocPage.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter状态管理',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: BlocPage(),
    );
  }
}

3.2、Scoped模式

推荐这种模式!该方式类似Provider。

3.2.1、新建Model

import 'dart:async';

class CountBloc {
  int _count = 0;
  StreamController<int> _controller;

  Stream<int> get count => _controller.stream;

  CountBloc() {
    _count = 0;
    _controller = StreamController.broadcast();
  }

  void increment() {
    _controller.sink.add(++_count);
  }

  void dispose() {
    _controller.close();
  }
}

3.2.2、新建两个页面(BlocPage和BlocPageTwo)

import 'package:flutter/material.dart';
import 'package:stateresearch/bloc/providers/CountProvider.dart';
import 'package:stateresearch/pages/BlocPageTwo.dart';

class BlocPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return _body(context);
  }

  Widget _body(BuildContext context) {
    final _bloc = CountProvider.of(context);

    return Scaffold(
      appBar: AppBar(
        title: Text("BlocPage"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('You have pushed the button this many times:'),
            StreamBuilder(
                stream: _bloc.count,
                initialData: 0,
                builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
                  return Text("${snapshot.data}");
                }),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) {
            return BlocPageTwo();
          }));
        },
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}
import 'package:flutter/material.dart';
import 'package:stateresearch/bloc/providers/CountProvider.dart';

class BlocPageTwo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return _body(context);
  }

  Widget _body(BuildContext context) {
    final _bloc = CountProvider.of(context);

    return Scaffold(
      appBar: AppBar(
        title: Text("BlocPageTwo"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('You have pushed the button this many times:'),
            StreamBuilder(
                stream: _bloc.count,
                initialData: 0,
                builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
                  return Text("${snapshot.data}");
                }),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          _bloc.increment();
        },
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

3.2.3、修改main文件

import 'package:flutter/material.dart';
import 'package:stateresearch/bloc/providers/CountProvider.dart';
import 'package:stateresearch/pages/BlocPage.dart';

void main() {
  runApp(CountProvider(child: MyApp()));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter状态管理',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: BlocPage(),
    );
  }
}

四、总结

我们发现,BLoC 和 ScopedModel / Provider 在跨页面间共享数组,

下篇会讲到 Redux ,它是一个很优秀的全局共享解决方案,可以考虑 全局redux + 局部bloc(rxdart) 管理方案!

上一篇 下一篇

猜你喜欢

热点阅读