您可能不再寻找解决方案,而是基于我想提供答案的问题的赞成票。
我不确定我是否正确理解了您的代码,并且看起来您正在自己实现 BLoC,所以这是一个免责声明,因为我提供了一个使用 Felix Angelov 的 BLoC 实现的解决方案(pub.dev/packages/bloc) .
下面描述的代码的结果
代码和方法:
首先我创建了一个空项目,并添加了 BLoC 库;在pubspec.yaml
我添加
flutter_bloc: ^3.2.0
然后我创建了一个BackendValidationBloc
包含一个事件ValidateInput
和多个状态的新块,如以下代码片段所示。
事件代码:
大多数时候,我从定义事件开始,这在我的示例中非常简单:
part of 'backend_validation_bloc.dart';
@immutable
abstract class BackendValidationEvent {}
class ValidateInput extends BackendValidationEvent {
final String input;
ValidateInput({@required this.input});
}
州代码:
那么您可能想要一个具有多个属性或多个状态的状态。我决定使用具有多个属性的一种状态,因为在我看来它更容易在 UI 中处理。在此示例中,我建议向用户提供反馈,因为通过后端验证输入可能需要一些时间。因此BackendValidationState
具有两种状态:loading
和validated
。
part of 'backend_validation_bloc.dart';
@immutable
class BackendValidationState {
final bool isInProcess;
final bool isValidated;
bool get isError => errorMessage.isNotEmpty;
final String errorMessage;
BackendValidationState(
{this.isInProcess, this.isValidated, this.errorMessage});
factory BackendValidationState.empty() {
return BackendValidationState(
isInProcess: false, isValidated: false);
}
BackendValidationState copyWith(
{bool isInProcess, bool isValidated, String errorMessage}) {
return BackendValidationState(
isValidated: isValidated ?? this.isValidated,
isInProcess: isInProcess ?? this.isInProcess,
// This is intentionally not defined as
// errorMessage: errorMessage ?? this.errorMessage
// because if the errorMessage is null, it means the input was valid
errorMessage: errorMessage,
);
}
BackendValidationState loading() {
return this.copyWith(isInProcess: true);
}
BackendValidationState validated({@required String errorMessage}) {
return this.copyWith(errorMessage: errorMessage, isInProcess: false);
}
}
集团代码:
最后,您通过定义调用后端的 bloc 将事件与状态“连接”:
import 'dart:async';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:meta/meta.dart';
part 'backend_validation_event.dart';
part 'backend_validation_state.dart';
class BackendValidationBloc
extends Bloc<BackendValidationEvent, BackendValidationState> {
@override
BackendValidationState get initialState => BackendValidationState.empty();
@override
Stream<BackendValidationState> mapEventToState(
BackendValidationEvent event,
) async* {
if (event is ValidateInput) {
yield this.state.loading();
String backendValidationMessage =
await this.simulatedBackendFunctionality(event.input);
yield this.state.validated(errorMessage: backendValidationMessage);
}
}
Future<String> simulatedBackendFunctionality(String input) async {
// This simulates delay of the backend call
await Future.delayed(Duration(milliseconds: 500));
// This simulates the return of the backend call
String backendValidationMessage;
if (input != 'hello') {
backendValidationMessage = "Input does not equal to 'hello'";
}
return backendValidationMessage;
}
}
用户界面代码:
如果您不熟悉如何在 UI 中使用已实现的 BLoC,这是前端代码使用状态将不同的值(用于实际错误消息和等待后端响应时的用户反馈)提供给 errorText 属性的TextField
。
import 'package:backend_validation_using_bloc/bloc/backend_validation_bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
void main() => runApp(App());
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: BlocProvider<BackendValidationBloc>(
create: (context) => BackendValidationBloc(), child: HomeScreen()),
);
}
}
class HomeScreen extends StatefulWidget {
HomeScreen({Key key}) : super(key: key);
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
TextEditingController textEditingController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: BlocBuilder<BackendValidationBloc, BackendValidationState>(
builder: (BuildContext context, BackendValidationState state) {
return TextField(
controller: textEditingController,
onChanged: (String currentValue) {
BlocProvider.of<BackendValidationBloc>(context)
.add(ValidateInput(input: currentValue));
},
decoration: InputDecoration(errorText: state.isInProcess ? 'Valiating input...' : state.errorMessage),
);
},
));
}
}
连接真实的后端
所以我有点伪造了一个后端,但是如果你想使用一个真实的后端,通常实现 aRepository
并将其传递给BLoC
构造函数中的 ,这使得使用后端的不同实现更容易(如果针对接口正确实现)。如果您想要更详细的教程,请查看Felix Angelov 的教程(它们非常好)
希望这对您或其他人有所帮助。