Flutter通用业务逻辑插件common_bloc的使用

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

Flutter通用业务逻辑插件common_bloc的使用

common_bloc 是一个用于简化Flutter应用中常见业务逻辑的BLoC(Business Logic Component)集合。它基于 bloccubit 构建,提供了几个常用的BLoC类来处理网络请求、任务执行和RSS数据获取等功能。

介绍

有时在同一个项目中需要创建多个执行相似功能的BLoC。common_bloc 提供了一组常见的BLoC以减少重复代码。这个库依赖于以下包:

主要功能

RestBloc

RestBloc 用于通过REST API进行网络请求。以下是使用示例:

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

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  [@override](/user/override)
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final restBloc = RestBloc('https://api.example.com');

  [@override](/user/override)
  void initState() {
    super.initState();
    fetchExampleData();
  }

  void fetchExampleData() {
    restBloc.get('path', fromJson: (json) => Data.fromJson(json));
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('RestBloc Example')),
      body: BlocBuilder<RestBloc, RestState>(
        bloc: restBloc,
        builder: (context, state) {
          return state.when(
            uninitialized: () => Center(child: Text('Uninitialized')),
            loading: () => Center(child: CircularProgressIndicator()),
            error: (error) => Center(child: Text('Error: $error')),
            loaded: (data, lastPath, timestamp) => Center(child: Text('Loaded: $data')),
          );
        },
      ),
    );
  }
}

RequestBloc

RequestBloc 用于执行需要响应或结果的任务。以下是使用示例:

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

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  [@override](/user/override)
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final requestBloc = RequestBloc();

  [@override](/user/override)
  void initState() {
    super.initState();
    performTask();
  }

  void performTask() {
    requestBloc.perform(() async => 'Hi!', 'Waving');
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('RequestBloc Example')),
      body: BlocBuilder<RequestBloc, RestState>(
        bloc: requestBloc,
        builder: (context, state) {
          return state.when(
            uninitialized: () => Center(child: Text('Uninitialized')),
            loading: () => Center(child: CircularProgressIndicator()),
            error: (error) => Center(child: Text('Error: $error')),
            loaded: (data, lastPath, timestamp) => Center(child: Text('Loaded: $data')),
          );
        },
      ),
    );
  }
}

RssBloc

RssBloc 用于从RSS URL获取并解析数据。以下是使用示例:

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

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  [@override](/user/override)
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final rssBloc = RssBloc();

  [@override](/user/override)
  void initState() {
    super.initState();
    fetchRssFeed();
  }

  void fetchRssFeed() {
    rssBloc.getFeed('http://www.publicbooks.org/tag/fiction/feed');
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('RssBloc Example')),
      body: BlocBuilder<RssBloc, RestState>(
        bloc: rssBloc,
        builder: (context, state) {
          return state.when(
            uninitialized: () => Center(child: Text('Uninitialized')),
            loading: () => Center(child: CircularProgressIndicator()),
            error: (error) => Center(child: Text('Error: $error')),
            loaded: (data, lastPath, timestamp) => Center(child: Text('Loaded: ${data.toString()}')),
          );
        },
      ),
    );
  }
}

更多关于Flutter通用业务逻辑插件common_bloc的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter通用业务逻辑插件common_bloc的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter开发中,使用BLoC(Business Logic Component)模式可以有效地管理应用的状态和业务逻辑。common_bloc这样的插件可以帮助我们实现一些通用的业务逻辑,从而减少重复代码和提高开发效率。尽管具体的common_bloc库可能因版本和社区维护情况而有所不同,但我们可以基于Flutter的BLoC模式给出一个通用的示例,展示如何在Flutter项目中使用BLoC来管理业务逻辑。

下面是一个简单的示例,展示如何创建一个BLoC来管理登录逻辑,这可以类比于使用common_bloc插件进行通用业务逻辑管理的场景。

1. 创建BLoC事件

首先,我们定义一个事件类来表示可以触发BLoC的动作。例如,登录事件:

// login_event.dart
import 'package:equatable/equatable.dart';

abstract class LoginEvent extends Equatable {
  const LoginEvent();

  @override
  List<Object?> get props => [];
}

class LoginButtonPressed extends LoginEvent {
  final String username;
  final String password;

  const LoginButtonPressed({required this.username, required this.password});

  @override
  List<Object?> get props => [username, password];
}

2. 创建BLoC状态

接下来,我们定义状态类来表示BLoC的当前状态。例如,登录状态:

// login_state.dart
import 'package:equatable/equatable.dart';

abstract class LoginState extends Equatable {
  const LoginState();

  @override
  List<Object?> get props => [];
}

class LoginInitial extends LoginState {
  const LoginInitial();
}

class LoginLoading extends LoginState {
  const LoginLoading();
}

class LoginSuccess extends LoginState {
  const LoginSuccess();
}

class LoginFailure extends LoginState {
  final String error;

  const LoginFailure({required this.error});

  @override
  List<Object?> get props => [error];
}

3. 创建BLoC

然后,我们创建BLoC类来管理状态和事件。例如,登录BLoC:

// login_bloc.dart
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:meta/meta.dart';
import 'login_event.dart';
import 'login_state.dart';

class LoginBloc extends Bloc<LoginEvent, LoginState> {
  LoginBloc() : super(LoginInitial());

  @override
  Stream<LoginState> mapEventToState(
    LoginEvent event,
  ) async* {
    if (event is LoginButtonPressed) {
      yield LoginLoading();
      // 模拟网络请求或验证逻辑
      await Future.delayed(const Duration(seconds: 2));
      if (event.username == 'admin' && event.password == 'password') {
        yield LoginSuccess();
      } else {
        yield LoginFailure(error: 'Invalid username or password');
      }
    }
  }
}

4. 使用BLoC在UI中

最后,我们在UI组件中使用BLoC来监听状态和触发事件。例如,登录页面:

// login_page.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'login_bloc.dart';
import 'login_event.dart';
import 'login_state.dart';

class LoginPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Login')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: BlocListener<LoginBloc, LoginState>(
          listener: (context, state) {
            if (state is LoginFailure) {
              ScaffoldMessenger.of(context).showSnackBar(
                SnackBar(content: Text(state.error)),
              );
            }
          },
          child: BlocBuilder<LoginBloc, LoginState>(
            builder: (context, state) {
              if (state is LoginLoading) {
                return CircularProgressIndicator();
              } else if (state is LoginSuccess) {
                return Center(child: Text('Login Successful'));
              } else {
                return Column(
                  children: <Widget>[
                    TextField(
                      decoration: InputDecoration(labelText: 'Username'),
                      onChanged: (value) {
                        context.read<LoginBloc>().add(
                          LoginButtonPressed(
                            username: value,
                            password: context.read<LoginBloc>().state
                                is LoginInitial
                                ? ''
                                : (context.read<LoginBloc>().currentState
                                        as LoginInitial)
                                    .toString(), // 这里只是一个占位符,实际上应该从另一个TextField获取密码
                          ),
                        );
                      },
                    ),
                    TextField(
                      obscureText: true,
                      decoration: InputDecoration(labelText: 'Password'),
                      onChanged: (value) {}, // 密码字段的onChange逻辑可以省略或处理密码显示/隐藏
                    ),
                    SizedBox(height: 20),
                    ElevatedButton(
                      onPressed: () {
                        final usernameController = TextEditingController.fromValue(
                          TextEditingValue(text: 'admin'), // 示例用户名
                        );
                        final passwordController = TextEditingController.fromValue(
                          TextEditingValue(text: 'password'), // 示例密码
                        );
                        context.read<LoginBloc>().add(
                          LoginButtonPressed(
                            username: usernameController.text,
                            password: passwordController.text,
                          ),
                        );
                      },
                      child: Text('Login'),
                    ),
                  ],
                );
              }
            },
          ),
        ),
      ),
    );
  }
}

注意:上述示例中,TextFieldonChanged处理逻辑是为了展示如何从UI组件中获取数据并触发BLoC事件,但在实际使用中,你可能需要更精细地控制何时触发登录事件(例如,在点击登录按钮时)。

这个示例展示了如何使用BLoC模式在Flutter中管理登录逻辑,你可以根据common_bloc插件的具体文档和功能,将其逻辑应用到你的项目中。通常,这样的插件会提供一些预定义的BLoC、事件和状态类,以简化常见业务逻辑的实现。

回到顶部