在 flutter 中将 Chopper 网络库与 flutter_bloc 库一起使用
Using Chopper networking library with flutter_bloc library in flutter
我正在使用 Chopper 库为我的业务逻辑调用 Rest APIs 和 flutter_bloc。
我的菜刀class
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);
}
}
我的模型class...未来就像
class StatementRes {
@JsonKey(name: 'StatusCode')
String statusCode;
@JsonKey(name: 'Desc')
String desc;
@JsonKey(name: 'Body')
Body body; //Nested model class
}
活动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];
}
状态class代码:
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
请指导我如何解决上述问题。
我认为最好使用 'BlocBuilder' 作为“BlocProvider”的子项,如下所示:
BlocProvider(
create: (context) => StatementBloc()..add(Fetch()),
child: BlocBuilder<StatementBloc, StatementState>(
builder: (mContext, state) {
// your code
}
),
),
并从 'initState()' 中删除此行:
stmtBloc = StatementBloc(StatementInitial());
我希望这能奏效。
我正在使用 Chopper 库为我的业务逻辑调用 Rest APIs 和 flutter_bloc。
我的菜刀class
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);
}
}
我的模型class...未来
class StatementRes {
@JsonKey(name: 'StatusCode')
String statusCode;
@JsonKey(name: 'Desc')
String desc;
@JsonKey(name: 'Body')
Body body; //Nested model class
}
活动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];
}
状态class代码:
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
请指导我如何解决上述问题。
我认为最好使用 'BlocBuilder' 作为“BlocProvider”的子项,如下所示:
BlocProvider(
create: (context) => StatementBloc()..add(Fetch()),
child: BlocBuilder<StatementBloc, StatementState>(
builder: (mContext, state) {
// your code
}
),
),
并从 'initState()' 中删除此行:
stmtBloc = StatementBloc(StatementInitial());
我希望这能奏效。