在flutter中使用Chopper网络库和flutter_bloc库
Posted
技术标签:
【中文标题】在flutter中使用Chopper网络库和flutter_bloc库【英文标题】:Using Chopper networking library with flutter_bloc library in flutter 【发布时间】:2021-02-06 21:44:44 【问题描述】:我正在使用 Chopper 库为我的业务逻辑调用 Rest API 和 flutter_bloc。
我的菜刀班
import 'package:chopper/chopper.dart';
import '../model/statement_res.dart';
import 'model_converter.dart';
part 'statement_api_service.chopper.dart';
@ChopperApi()
abstract class StatementApiService extends ChopperService
// 6
@Get(
path: 'getStatement')
Future<Response<StatementRes>> getStatement(
@Query() String AccountNo,
@Query() String StartDate,
@Query() String EndDate,
);
// 8
static StatementApiService create()
// 9
final client = ChopperClient(
// 10
baseUrl: 'SERVER_URL',
interceptors: [HttpLoggingInterceptor()],
converter: ModelConverter(),
errorConverter: JsonConverter(),
// 11
services: [
_$StatementApiService(),
],
);
// 12
return _$StatementApiService(client);
我的模型类... Future
class StatementRes
@JsonKey(name: 'StatusCode')
String statusCode;
@JsonKey(name: 'Desc')
String desc;
@JsonKey(name: 'Body')
Body body; //Nested model class
事件类代码:
import 'package:equatable/equatable.dart';
abstract class StatementEvent extends Equatable
const StatementEvent();
class GetStatement extends StatementEvent
final String accountNo;
final startDate;
final endDate;
const GetStatement(this.accountNo, this.startDate, this.endDate);
@override
List<Object> get props => [accountNo, startDate, endDate];
状态类代码:
import 'package:equatable/equatable.dart';
import '../model/statement_res.dart';
import 'package:chopper/chopper.dart';
abstract class StatementState extends Equatable
const StatementState();
class StatementInitial extends StatementState
const StatementInitial();
@override
List<Object> get props => [];
class StatementLoading extends StatementState
const StatementLoading();
@override
List<Object> get props => [];
class StatementLoaded extends StatementState
final Response<StatementRes> statementRes;
const StatementLoaded(this.statementRes);
@override
List<Object> get props => [statementRes];
class StatementError extends StatementState
final String message;
const StatementError(this.message);
@override
List<Object> get props => [message];
这是我的 Bloc(mapEventToState) 代码
import 'dart:async';
import 'package:bloc/bloc.dart';
import '../service/statement_api_service.dart';
import './bloc.dart';
class StatementBloc
extends Bloc<StatementEvent, StatementState>
StatementBloc(StatementState initialState) : super(initialState);
@override
StatementState get initialState => StatementInitial();
@override
Stream<StatementState> mapEventToState(
StatementEvent event,
) async*
yield StatementLoading();
if (event is GetStatement)
try
final statementResponse =
await StatementApiService.create()
.getStatement(
AccountNo: event.accountNo,
StartDate: event.startDate,
EndDate: event.endDate);
yield StatementLoaded(statementResponse);
catch (e)
yield StatementError("Failed to fetch Statement");
我正在尝试从我的 UI 中调用 Bloc 的代码,如下所示:
class MyHomePage extends StatefulWidget
final String title;
MyHomePage(Key key, this.title) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
class _MyHomePageState extends State<MyHomePage>
StatementBloc stmtBloc;
@override
void initState()
super.initState();
stmtBloc = StatementBloc(StatementInitial());
@override
void didChangeDependencies()
super.didChangeDependencies();
stmtBloc.add(
GetStatement("1155328002", "09-OCT-2020", "19-OCT-2020"));
@override
Widget build(BuildContext context)
return Scaffold(
appBar: AppBar(
title: Text("Testing - Bloc"),
),
body: Container(
padding: EdgeInsets.symmetric(vertical: 16),
alignment: Alignment.center,
child:
BlocBuilder<StatementBloc, StatementState>(
builder: (context, state)
if (state is StatementLoading)
print("#################");
print("**********StatementLoading*************");
print("#################");
return buildLoading();
else if (state is StatementLoaded)
print("#################");
,print("**********StatementLoaded*************");
print("#################");
return buildColumnWithData(
context, state.sStatementRes.body.responseDesc);
else
print("#################");
print("**********Else*************");
print("#################");
return buildLoading();
,
),
),
);
我能够成功调用 API 并能够获得响应。但无法在 UI 中显示。收到以下异常:
flutter: ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
flutter: The following assertion was thrown building Container(center, padding: EdgeInsets(0.0, 16.0, 0.0,
flutter: 16.0)):
flutter: BlocProvider.of() called with a context that does not contain a Cubit of type
flutter: StatementBloc.
flutter: No ancestor could be found starting from the context that was passed to
flutter: BlocProvider.of<StatementBloc>().
flutter:
flutter: This can happen if the context you used comes from a widget above the BlocProvider.
flutter:
flutter: The context used was: BlocBuilder<StatementBloc,
flutter: StatementState>(dirty, state: _BlocBuilderBaseState<StatementBloc,
flutter: StatementState>#4c48e(lifecycle state: created))
flutter:
flutter:
flutter: The relevant error-causing widget was:
flutter: Container
flutter: file:/lib/views/my_home_page.dart:50:13
请指导我如何解决上述问题。
【问题讨论】:
【参考方案1】:我认为最好将“BlocBuilder”用作“BlocProvider”的子级,如下所示:
BlocProvider(
create: (context) => StatementBloc()..add(Fetch()),
child: BlocBuilder<StatementBloc, StatementState>(
builder: (mContext, state)
// your code
),
),
并从 'initState()' 中删除这一行:
stmtBloc = StatementBloc(StatementInitial());
我希望这行得通。
【讨论】:
谢谢,您的回答帮助我解决了这个问题。以上是关于在flutter中使用Chopper网络库和flutter_bloc库的主要内容,如果未能解决你的问题,请参考以下文章
Dart Flutter - 使用 Chopper 获取 WordPress 自定义帖子类型
在颤动中使用 Chopper 库将 JSON 响应转换为模型对象?