我正在为 RxDart 苦苦挣扎(也许只是直接进行 Rx 编程)。我目前有一个有状态的小部件,它在它的didChangeDependencies()
. 该调用发出并通过 http 请求获取数据并将其添加到流中。我正在使用BehaviorSubject
,这很好用。我有使用 StreamBuilders 的子小部件,它们获取数据没有问题。我的问题在于处理错误。如果我的 http 请求失败,我会使用流水化流,addError('whatever error')
但我的子小部件的 StreamBuilder 没有收到该错误。它什么也得不到。
所以我有几个问题。
- 这是预期的吗?
- 不应该在 StreamBuilder 中进行错误处理吗?理想情况下,如果出现问题,我想在 UI 中显示一些东西,所以不知道该怎么做。
- 我可以让我的孩子小部件有状态并使用
stream.listen
. 我确实收到了那里的错误,但是拥有它和 StreamBuilder 似乎有点过头了。 - 我在这里遗漏了一些关于流和错误处理的基本知识吗?
这是我的集团:
final _plans = BehaviorSubject<List<PlanModel>>();
Observable<List<PlanModel>> get plans => _plans.stream;
fetchPlans() async {
try {
final _plans = await _planRepository.getPlans();
_plans.add(_plans);
}
on AuthenticationException {
_plans.addError('authentication error');
}
on SocketException {
_plans.addError('no network connection');
}
catch(error) {
_plans.addError('fetch unsuccessful');
}
}
简化的父小部件:
class PlanPage extends StatefulWidget {
@override
PlanPageState createState() {
return new PlanPageState();
}
}
class PlanPageState extends State<PlanPage> {
@override
void didChangeDependencies() async {
super.didChangeDependencies();
var planBloc = BaseProvider.of<PlanBloc>(context);
planBloc.fetchPlans();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar( title: const Text('Your Plan') ),
body: PlanWrapper()
);
}
}
带有 StreamBuilder 的简化子小部件:
class PlanWrapper extends StatelessWidget {
@override
Widget build(BuildContext context) {
var planBloc = BaseProvider.of<PlanBloc>(context);
return StreamBuilder(
stream: planBloc.plans,
builder: (BuildContext context, AsyncSnapshot<List<PlanModel>> plans) {
if (plans.hasError) {
//ERROR NEVER COMES IN HERE
switch(plans.error) {
case 'authentication error':
return RyAuthErrorCard();
case 'no network connection':
return RyNetworkErrorCard();
default:
return RyGenericErrorCard(GeneralException().errorMessages()['message']);
}
}
if (plans.hasData && plans.data.isNotEmpty) {
return ListView(
physics: const AlwaysScrollableScrollPhysics(),
children: _buildPlanTiles(context, plans.data)
);
}
return Center(child: const CircularProgressIndicator());
}
);
}
}