Flutter网络请求管理插件bloc_network的使用

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

Flutter网络请求管理插件bloc_network的使用

概述

bloc_network 是一个支持 bloc 生态系统的辅助包,旨在减少构建用于管理网络请求状态的 bloc 时所需的样板代码。它与 flutter_bloc 小部件和API完全兼容,并提供了一种有见地且一致的标准来管理网络操作。

Stint

Pub

特性

  • 支持通过继承 QueryBlocQueryCubit 来构建类似查询的网络请求。
  • 支持通过继承 MutationBlocMutationCubit 来构建类似变更的网络请求。
  • 提供预定义的状态和状态转换。

使用方法

步骤 1: 导入并构造 Bloc

首先,导入 bloc_network 包并为网络操作构造一个 bloc,指定一个 repositoryCallback。推荐使用 仓库模式 来处理网络请求。

import 'package:bloc_network/bloc_network.dart';

class CostCubit extends QueryCubit<int> {
  @override
  Future<int> repositoryCallback(Object? extra) async {
    // 模拟异步操作。通常这里会执行HTTP GET请求。
    await Future<void>.delayed(const Duration(seconds: 1));
    return 5;
  }
}

步骤 2: (可选) 定义类型别名

可以为网络请求的状态定义类型别名,以提高代码的可读性和一致性。

typedef CostState = QueryState<int>;
typedef CostLoading = QueryLoading<int>;
typedef CostError = QueryError<int>;
typedef CostAvailable = QuerySuccess<int>;

步骤 3: 使用 Bloc

确保 bloc 已经通过 BlocProvider 提供给 widget 树,然后触发网络请求并在界面上响应其状态变化。

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: BlocProvider<CostCubit>(
        create: (_) => CostCubit(),
        child: Scaffold(
          appBar: AppBar(title: Text('Network Request Demo')),
          body: Center(child: CostWidget()),
        ),
      ),
    );
  }
}

class CostWidget extends StatefulWidget {
  @override
  _CostWidgetState createState() => _CostWidgetState();
}

class _CostWidgetState extends State<CostWidget> {
  @override
  void initState() {
    super.initState();
    // 触发网络请求:
    context.read<CostCubit>().fetchData();
  }

  @override
  Widget build(BuildContext context) {
    // 响应网络请求的状态:
    return BlocBuilder<CostCubit, CostState>(
      builder: (context, state) {
        if (state is CostError) {
          return Text('Something went wrong! Please retry.');
        }
        if (state is CostAvailable) {
          return Text('The cost for this item is ${state.data}');
        }
        return Text('Loading...');
      },
    );
  }
}

示例代码

以下是完整的示例代码,展示了如何在 main.dart 文件中使用 CostCubit

// ignore_for_file: avoid_print

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

void main() {
  final cubit = CostCubit();
  cubit.stream.listen((state) => print('state changed to: $state'));
  cubit.fetchData();
  
  runApp(MyApp(cubit: cubit));
}

class MyApp extends StatelessWidget {
  final CostCubit cubit;

  MyApp({required this.cubit});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: BlocProvider<CostCubit>.value(
        value: cubit,
        child: Scaffold(
          appBar: AppBar(title: Text('Network Request Demo')),
          body: Center(child: CostWidget()),
        ),
      ),
    );
  }
}

class CostWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocBuilder<CostCubit, CostState>(
      builder: (context, state) {
        if (state is CostError) {
          return Text('Something went wrong! Please retry.');
        }
        if (state is CostAvailable) {
          return Text('The cost for this item is ${state.data}');
        }
        return Text('Loading...');
      },
    );
  }
}

class CostCubit extends QueryCubit<int> {
  @override
  Future<int> repositoryCallback(Object? extra) async {
    // 模拟异步操作。通常这里会执行HTTP GET请求。
    await Future<void>.delayed(const Duration(seconds: 1));
    return 5;
  }
}

通过以上步骤,您可以轻松地将 bloc_network 集成到您的 Flutter 应用程序中,从而简化网络请求的管理和状态处理。


更多关于Flutter网络请求管理插件bloc_network的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter网络请求管理插件bloc_network的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter项目中使用bloc_network插件进行网络请求管理的示例。bloc_network是一个结合了Bloc状态管理和dio网络请求库的强大工具,它使得网络请求的管理更加清晰和模块化。

首先,确保你的Flutter项目中已经添加了blocbloc_network的依赖。你可以在pubspec.yaml文件中添加以下依赖:

dependencies:
  flutter:
    sdk: flutter
  bloc: ^8.0.0 # 请检查最新版本
  flutter_bloc: ^8.0.0 # 请检查最新版本
  dio: ^4.0.0 # 请检查最新版本
  bloc_network: ^1.0.0 # 请检查最新版本,这个库可能还在不断更新中

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

接下来,我们将创建一个简单的网络请求Bloc,用于从API获取数据。

1. 定义网络请求事件和数据模型

首先,我们定义一个网络请求事件和数据模型。

// events/fetch_data.dart
import 'package:flutter_bloc/flutter_bloc.dart';

part 'fetch_data_event.g.dart';

@freezed
abstract class FetchDataEvent with _$FetchDataEvent {
  const factory FetchDataEvent.fetchRequested() = _FetchDataRequested;
}

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

part 'fetch_data_state.g.dart';

@freezed
abstract class FetchDataState with _$FetchDataState {
  const factory FetchDataState.initial() = _Initial;
  const factory FetchDataState.loading() = _Loading;
  const factory FetchDataState.success(List<String> data) = _Success;
  const factory FetchDataState.failure(String error) = _Failure;

  @override
  String toString() {
    return when(
      initial: () => 'Initial',
      loading: () => 'Loading...',
      success: (data) => 'Success: $data',
      failure: (error) => 'Failure: $error',
    );
  }
}

2. 创建Bloc

然后,我们创建一个Bloc来处理这些事件并返回相应的状态。

// blocs/fetch_data_bloc.dart
import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:bloc_network/bloc_network.dart';
import 'package:dio/dio.dart';
import 'package:your_app/events/fetch_data.dart';
import 'package:your_app/states/fetch_data_state.dart';

part 'fetch_data_bloc.g.dart';

class FetchDataBloc extends Bloc<FetchDataEvent, FetchDataState> with BlocNetwork {
  FetchDataBloc() : super(FetchDataState.initial()) {
    on<FetchDataEvent.fetchRequested>(
      _fetchData,
      transformer: requestTransformer(),
    );
  }

  Future<void> _fetchData(
    FetchDataEvent.fetchRequested event,
    Emitter<FetchDataState> emit,
  ) async {
    emit(FetchDataState.loading());
    try {
      final response = await dio.get('https://jsonplaceholder.typicode.com/posts');
      final data = response.data.map((post) => post['title'] as String).toList();
      emit(FetchDataState.success(data));
    } catch (error) {
      emit(FetchDataState.failure(error.toString()));
    }
  }
}

3. 使用Bloc在UI中显示数据

最后,我们在UI中使用BlocBuilder来监听Bloc的状态并更新UI。

// pages/home_page.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:your_app/blocs/fetch_data_bloc.dart';
import 'package:your_app/states/fetch_data_state.dart';

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Fetch Data Example'),
      ),
      body: Center(
        child: BlocBuilder<FetchDataBloc, FetchDataState>(
          builder: (context, state) {
            if (state is FetchDataState.loading) {
              return CircularProgressIndicator();
            } else if (state is FetchDataState.success) {
              return ListView.builder(
                itemCount: state.data.length,
                itemBuilder: (context, index) {
                  return ListTile(
                    title: Text(state.data[index]),
                  );
                },
              );
            } else if (state is FetchDataState.failure) {
              return Text('Error: ${state.error}');
            } else {
              return Text('No Data');
            }
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => context.read<FetchDataBloc>().add(FetchDataEvent.fetchRequested()),
        tooltip: 'Fetch Data',
        child: Icon(Icons.refresh),
      ),
    );
  }
}

4. 在主应用中使用HomePage

确保在你的主应用文件中使用HomePage

// main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:your_app/blocs/fetch_data_bloc.dart';
import 'package:your_app/pages/home_page.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: BlocProvider(
        create: (context) => FetchDataBloc(),
        child: HomePage(),
      ),
    );
  }
}

现在,你应该已经成功地在Flutter项目中使用了bloc_network插件来管理网络请求。这个示例展示了如何定义一个Bloc来处理网络请求事件,并在UI中根据Bloc的状态更新界面。

回到顶部