Flutter状态管理设计模式插件flutter_bloc_patterns的使用

发布于 1周前 作者 ionicwang 来自 Flutter

Flutter BLoC Patterns 使用指南

Flutter BLoC Patterns 是一套基于 flutter_bloc 库构建的常用 BLoC 用例集合。本文将介绍如何使用这个插件,并提供完整的示例代码。

关键概念

BLoC

BLoC,即 Business Logic Component,是一种用于 Flutter 的状态管理系统。其主要目标是将业务逻辑与表示层分离。BLoC 处理用户操作或其他事件,并生成新的状态供视图渲染。

Repository

Repository 负责处理数据操作。它知道从哪里获取数据以及在数据更新时需要调用哪些 API。Repository 可以使用单一数据源,也可以作为不同数据源之间的中介,例如数据库、Web 服务和缓存。

ViewStateBuilder

ViewStateBuilder 负责根据视图状态构建 UI。它是 BlocBuilder 小部件的封装,因此接受一个 bloc 对象和一组方便的回调函数,对应于每个可能的状态:

  • initial:告知表示层视图处于初始状态,尚未采取任何操作。
  • loading:告知表示层正在加载数据,可以显示加载指示器。
  • refreshing:告知表示层正在刷新数据,可以显示刷新指示器或当前列表项的状态。
  • data:告知表示层加载已完成,并检索到非空数据。
  • empty:告知表示层加载已完成,但检索到空数据。
  • error:告知表示层加载或刷新结束时发生错误,并提供发生的错误。

ViewStateListener

ViewStateListener 负责根据视图状态执行操作。应仅在响应状态更改时使用此功能,例如导航、显示 SnackBar 等。ViewStateListenerBlocListener 小部件的封装,因此接受一个 bloc 对象以及一个 child 小部件和一组与给定状态对应的方便的回调函数。

示例演示

ListBloc

使用方法

以下是一个简单的 ListBloc 示例,展示如何使用该插件来获取和显示列表数据。

import 'package:flutter/material.dart';
import 'package:flutter_bloc_patterns/list.dart';

class Item {
  final String name;

  Item(this.name);
}

class ItemRepository extends ListRepository<Item> {
  @override
  Future<List<Item>> getAll() async {
    // 模拟网络请求
    await Future.delayed(Duration(seconds: 2));
    return [
      Item('Item 1'),
      Item('Item 2'),
      Item('Item 3'),
    ];
  }
}

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: ListScreen(),
    );
  }
}

class ListScreen extends StatelessWidget {
  final listBloc = ListBloc<Item>(ItemRepository());

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('List BLoC Example'),
      ),
      body: ViewStateBuilder<List<Item>>(
        bloc: listBloc,
        initial: (context) => Center(child: Text('Initial State')),
        loading: (context) => Center(child: CircularProgressIndicator()),
        data: (context, items) => ListView.builder(
          itemCount: items.length,
          itemBuilder: (context, index) {
            final item = items[index];
            return ListTile(
              title: Text(item.name),
            );
          },
        ),
        empty: (context) => Center(child: Text('No Data Found')),
        error: (context, error) => Center(child: Text('Error: $error')),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => listBloc.loadItems(),
        child: Icon(Icons.refresh),
      ),
    );
  }
}

FilterListBloc

使用方法

以下是一个带有过滤功能的 FilterListBloc 示例。

import 'package:flutter/material.dart';
import 'package:flutter_bloc_patterns/filter_list.dart';

class Item {
  final String name;
  final bool isFavorite;

  Item(this.name, this.isFavorite);
}

class ItemRepository extends FilterListRepository<Item, bool> {
  @override
  Future<List<Item>> getAll() async {
    await Future.delayed(Duration(seconds: 2));
    return [
      Item('Item 1', true),
      Item('Item 2', false),
      Item('Item 3', true),
    ];
  }

  @override
  Future<List<Item>> getBy(bool filter) async {
    final allItems = await getAll();
    return allItems.where((item) => item.isFavorite == filter).toList();
  }
}

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: FilterListScreen(),
    );
  }
}

class FilterListScreen extends StatefulWidget {
  @override
  _FilterListScreenState createState() => _FilterListScreenState();
}

class _FilterListScreenState extends State<FilterListScreen> {
  final filterListBloc = FilterListBloc<Item, bool>(ItemRepository());
  bool _filter = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Filter List BLoC Example'),
      ),
      body: Column(
        children: [
          SwitchListTile(
            title: Text('Show Favorites'),
            value: _filter,
            onChanged: (value) {
              setState(() {
                _filter = value;
                filterListBloc.loadItems(filter: _filter);
              });
            },
          ),
          Expanded(
            child: ViewStateBuilder<List<Item>>(
              bloc: filterListBloc,
              initial: (context) => Center(child: Text('Initial State')),
              loading: (context) => Center(child: CircularProgressIndicator()),
              data: (context, items) => ListView.builder(
                itemCount: items.length,
                itemBuilder: (context, index) {
                  final item = items[index];
                  return ListTile(
                    title: Text(item.name),
                  );
                },
              ),
              empty: (context) => Center(child: Text('No Data Found')),
              error: (context, error) => Center(child: Text('Error: $error')),
            ),
          ),
        ],
      ),
    );
  }
}

ConnectionBloc

使用方法

以下是一个展示如何使用 ConnectionBloc 监听网络连接状态变化的示例。

import 'package:flutter/material.dart';
import 'package:flutter_bloc_patterns/connection.dart';
import 'package:connectivity_plus/connectivity_plus.dart';

class ConnectivityPlusRepository implements ConnectionRepository {
  final Connectivity _connectivity = Connectivity();

  @override
  Stream<Connection> observe() {
    return MergeStream([
      Stream.fromFuture(_connectivity.checkConnectivity()),
      _connectivity.onConnectivityChanged,
    ]).map(
          (ConnectivityResult result) =>
          result != ConnectivityResult.none ? Connection.online : Connection.offline,
    );
  }
}

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: ConnectionScreen(),
    );
  }
}

class ConnectionScreen extends StatelessWidget {
  final connectionBloc = ConnectionBloc(ConnectivityPlusRepository());

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Connection BLoC Example'),
      ),
      body: ConnectionBuilder(
        bloc: connectionBloc,
        online: (context) => Center(child: Text('You are online')),
        offline: (context) => Center(child: Text('You are offline')),
      ),
    );
  }
}

以上是 flutter_bloc_patterns 插件的基本使用方法及示例代码。通过这些示例,您可以更好地理解和应用 BLoC 模式进行状态管理。更多详细信息和完整示例请参考 GitHub 上的项目文档。


更多关于Flutter状态管理设计模式插件flutter_bloc_patterns的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter状态管理设计模式插件flutter_bloc_patterns的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter项目中使用flutter_bloc_patterns插件来进行状态管理设计模式的示例。flutter_bloc_patterns是一个用于帮助开发者在Flutter项目中实现常见BLoC(Business Logic Component)设计模式的库。

1. 添加依赖

首先,你需要在你的pubspec.yaml文件中添加flutter_blocflutter_bloc_patterns的依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_bloc: ^8.0.0  # 请检查最新版本
  flutter_bloc_patterns: ^0.3.0  # 请检查最新版本

然后运行flutter pub get来安装这些依赖。

2. 创建BLoC和状态

假设我们有一个简单的计数器应用,我们首先需要定义我们的状态和事件。

import 'package:flutter_bloc/flutter_bloc.dart';

// Counter Event
enum CounterEvent { increment, decrement }

// Counter State
class CounterState extends Equatable {
  final int count;

  CounterState(this.count) : super([count]);

  // Helper function to create a new state with an incremented/decremented count
  CounterState copyWith(int count) => CounterState(count);
}

3. 创建BLoC

然后,我们需要创建一个BLoC来处理这些事件并生成新的状态。

import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_bloc_patterns/flutter_bloc_patterns.dart';

class CounterBloc extends Bloc<CounterEvent, CounterState> with RepositoryBloc<CounterEvent, CounterState> {
  CounterBloc() : super(CounterState(0)) {
    on<CounterEvent>((event, emit) {
      switch (event) {
        case CounterEvent.increment:
          emit(currentState.copyWith(currentState.count + 1));
          break;
        case CounterEvent.decrement:
          emit(currentState.copyWith(currentState.count - 1));
          break;
      }
    });
  }
}

4. 使用BLoC在UI中

现在,我们可以在我们的Flutter应用中使用这个BLoC来管理状态并更新UI。

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

// Counter Widget
class CounterWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (context) => CounterBloc(),
      child: Scaffold(
        appBar: AppBar(title: Text('Counter App')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text('You have pushed the button this many times:'),
              BlocBuilder<CounterBloc, CounterState>(
                buildWhen: (previous, current) => previous.count != current.count,
                builder: (context, state) {
                  return Text(
                    '${state.count}',
                    style: Theme.of(context).textTheme.headline4,
                  );
                },
              ),
            ],
          ),
        ),
        floatingActionButton: Row(
          mainAxisAlignment: MainAxisAlignment.end,
          children: <Widget>[
            FloatingActionButton(
              onPressed: () => context.read<CounterBloc>().add(CounterEvent.increment),
              tooltip: 'Increment',
              child: Icon(Icons.add),
            ),
            SizedBox(width: 10),
            FloatingActionButton(
              onPressed: () => context.read<CounterBloc>().add(CounterEvent.decrement),
              tooltip: 'Decrement',
              child: Icon(Icons.remove),
            ),
          ],
        ),
      ),
    );
  }
}

// Main Function
void main() {
  runApp(MaterialApp(home: CounterWidget()));
}

5. 运行应用

现在,你可以运行你的Flutter应用,并看到一个简单的计数器应用,其中使用了flutter_bloc_patterns插件来管理状态。

总结

这个示例展示了如何使用flutter_bloc_patterns插件在Flutter项目中实现BLoC设计模式。通过定义状态和事件,创建BLoC来处理这些事件,并在UI中使用BLoC来更新状态,你可以实现一个响应式且易于维护的用户界面。

回到顶部