我正在使用inject.dart将我的块作为单例注入,这是一种不好的做法,即会导致内存泄漏吗?
由于我使用的所有流都是来自 RxDart 的广播流,我想知道单例是否会工作得更好?
如果不是不好的做法,那么关闭流的最佳位置是什么?由于其他小部件可能仍在使用流,因此在有状态小部件(订阅 bloc)的 Dispose() 中执行此操作是否会导致问题?
我有一个EmailScreen(有状态的小部件),它有一个文本输入和一个按钮。仅当输入有效的电子邮件时该按钮才会启用。
我正在使用 Bloc,我的屏幕上有InitialEmailState和ValidEmailInputState,并且当我运行该应用程序时它工作正常。
在我的小部件测试中,在 bloc 有机会更新状态之前,第二个期望失败了:
\n\n\n testWidgets(\'when valid email is input, button is enabled\', (tester) async {\n const validEmail = \'email@provider.com\';\n\n emailBloc.listen((event) {\n print(\'NEW EVENT: \' + event.toString());\n });\n\n await bootUpWidget(tester, emailScreen);\n\n final BottomButton button = tester.widget(\n find.widgetWithText(BottomButton, \'CONTINUE\'));\n\n expect(button.enabled, isFalse);\n\n await tester.enterText(find.byType(TextInputScreen), validEmail);\n await tester.pumpAndSettle();\n\n expect(button.enabled, isTrue);\n });\nRun Code Online (Sandbox Code Playgroud)\n\n这是我得到的输出:
\n\nNEW EVENT: InitialEmailState\n\xe2\x95\x90\xe2\x95\x90\xe2\x95\xa1 EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK \xe2\x95\x9e\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\nThe following TestFailure object was thrown running a test:\n …Run Code Online (Sandbox Code Playgroud) 我们有一个 Flutter 应用程序,它使用 websocket 进行服务器发起的通信。我们使用 flutter_bloc 作为整个应用程序的状态管理机制。UI 事件通过 Bloc 状态转换和 BlocBuilder 小部件传送到小部件。
另一个要求是,有些小部件应该根据通过 websocket 从服务器接收到的特定事件来重新渲染。
StreamBuilder 是对 Websocket 上接收到的事件做出反应的自然方式。但不确定将其合并到使用 Blocs 的 UI 小部件中的最佳方法。
当 Bloc 和 websocket 通道一起使用时,希望社区提供有关干净地构造代码的意见。
我正在尝试使用 Hydrated_bloc 库保持状态,问题是该库的所有示例都非常基本,我想通过使用示例 api 休息来维护状态,但我仍然无法实现此示例的逻辑:
userbloc_bloc.dart
import 'dart:async';
import 'package:di/users/model/user.dart';
import 'package:di/users/repository/cloud_api_repository.dart';
import 'package:equatable/equatable.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
part 'userbloc_event.dart';
part 'userbloc_state.dart';
class UserblocBloc extends HydratedBloc<UserblocEvent, UserblocState> {
@override
UserblocState get initialState {
return super.initialState ?? UserblocInitial();
}
@override
UserblocState fromJson(Map<String, dynamic> json) {
try {
final usermodel = UserModel.fromJson(json);
return UserblocLoaded(usermodel);
} catch (_) {
return null;
}
}
@override
Map<String, dynamic> toJson(UserblocState state) {
if (state is UserblocLoaded) {
return state.userModel.toJson();
}else{
return null;
}
}
@override
Stream<UserblocState> mapEventToState(
UserblocEvent …Run Code Online (Sandbox Code Playgroud) 我的 Bloc 状态没有更新,我发现问题可能是Map<String, Map<String, String>未正确比较的属性。如果我错了,请纠正我,但状态会在其他属性更改时更新,而不是在imageUrls属性更新时更新。
这些是我的状态对象
abstract class PropertiesState extends Equatable {
const PropertiesState();
}
class PropertiesLoaded extends PropertiesState {
final int count;
final List<Property> properties;
final Map<String, Map<String, String>> imageUrls;
const PropertiesLoaded({
this.count,
this.properties,
this.imageUrls,
});
@override
List<Object> get props => [count, properties, imageUrls];
}
Run Code Online (Sandbox Code Playgroud)
imageUrls 字段可以有任何字符串键/值对。我无法找到有关如何执行此操作的任何信息。
谢谢您的帮助!
我有一个嵌套结构,如下所示:
List<Areas>
|-- List<Topics>
| |-- List<Exercises>
Run Code Online (Sandbox Code Playgroud)
这是我的应用程序的工作流程:
API并显示列表AreasArea并转到下一个屏幕API并显示主题列表Topic并转到下一个屏幕API并显示练习列表我开始使用BloC,但我不确定是否应该对每种类型的数据使用一个 Bloc(因此一个 bloc for Areas,另一个 for Topics,另一个 for Exercises)或仅在一个 Bloc 中处理整个结构。
我看到一个问题,其中State包含整个结构,并且每次从 中获取嵌套列表时都需要更新API。也许这会导致内存问题?
另一方面,每种数据类型都有一个 Bloc 将使它们之间的通信变得复杂。
state management如果更有意义的话,我也愿意改用另一种技术。
任何帮助,将不胜感激。
多谢。
我_CastError 在这段代码的最后一行遇到错误
BlocBuilder buildUsernameField() {
return BlocBuilder<ProfileBloc, ProfileState>(
buildWhen: (previous, current) => previous != current && current is EditingUserInfo,
builder: (context, state) => TextField(
keyboardType: TextInputType.name,
controller: TextEditingController(
text: (state as EditingUserInfo).username.value),
Run Code Online (Sandbox Code Playgroud)
这么说
I/flutter (26787): The following _CastError was thrown building BlocBuilder<ProfileBloc, ProfileState>(dirty, state:
I/flutter (26787): _BlocBuilderBaseState<ProfileBloc, ProfileState>#25b87):
I/flutter (26787): type 'Success' is not a subtype of type 'EditingUserInfo' in type cast
Run Code Online (Sandbox Code Playgroud)
所以发生的事情是,当我处于另一种状态(成功)时,它会尝试构建该小部件。但在buildWhen参数中,我指定小部件仅应在状态为 时构建EditingUserInfo。
据我了解,这个错误不应该发生。
这是我的ProfileState:
I/flutter (26787): The following _CastError was thrown …Run Code Online (Sandbox Code Playgroud) 我使用 Flutter 工作了很长时间,并发布了很多产品。我从来没有真正喜欢过 BLoC,更喜欢使用 Provider 或后来的 Riverpod。
我只是不明白该事件的概念。为什么我们还需要它?我很困惑,因为它的实际受欢迎程度...... BLoC 有 Cubit 子类,似乎使用起来更简单,但每个人都只是不停地说:“Cubit 更简单,但功能不那么强”。但有什么限制呢?
我什至认为肘尺更有用,同时也更简单:
示例:用户点击某些产品的“添加到购物车”按钮。
肘:
cartCubit.addProduct(productId);
Run Code Online (Sandbox Code Playgroud)
集团:
cartBloc.addEvent(UserAddsProductEvent(productId));
Run Code Online (Sandbox Code Playgroud)
在它们里面:
肘:
void addProduct(String productId) async {
//some validation...
if(...){...}
final result = await cartRepo.addProduct(id);
if(result == ...) {
state = someState;
//....
}
Run Code Online (Sandbox Code Playgroud)
集团:
void addEvent(CartEvent event) {
if (event is UserAddsProductEvent) {
_addProduct(event.productId)
} else if (event is....) {
//.....
}
}
void _addProduct(String productId) async {
//some validation...
if(...){...}
final result = …Run Code Online (Sandbox Code Playgroud) 假设我们使用以下代码导航到“PageA”:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return BlocProvider(
create: (context) => BlocA(),
child: PageA(),
);
},
),
);
Run Code Online (Sandbox Code Playgroud)
当“PageA”导航到“PageB”时。我如何访问“BLocA”?我尝试使用以下代码从“PageA”导航到“PageB”,但它崩溃了。
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return BlocProvider(
create: (context) => contxt.read<BlocA>(),
child: PageB(),
);
},
),
);
Run Code Online (Sandbox Code Playgroud) 我正在关注到新块 8.0.0 的迁移。我正在尝试删除 mapEventToState但 我在这样做时遇到困难。你能帮我看看该怎么做吗?我已经在下面尝试过,但它不起作用。
旧代码:
class SignInBloc extends Bloc<SignInEvent, SignInState> {
final AuthenticationRepository authenticationRepository;
final UserDataRepository userDataRepository;
SignInBloc(
{required this.authenticationRepository,
required this.userDataRepository})
: super(SignInInitialState());
SignInState get initialState => SignInInitialState();
@override
Stream<SignInState> mapEventToState(
SignInEvent event,
) async* {
if (event is SignInWithGoogle) {
yield* mapSignInWithGoogleToState();
}
}
Stream<SignInState> mapSignInWithGoogleToState() async* {
yield SignInWithGoogleInProgressState();
try {
String res = await authenticationRepository.signInWithGoogle();
yield SignInWithGoogleCompletedState(res);
} catch (e) {
print(e);
yield SignInWithGoogleFailedState();
}
}
...
Run Code Online (Sandbox Code Playgroud)
迁移代码(不起作用):
class SignInBloc extends Bloc<SignInEvent, …Run Code Online (Sandbox Code Playgroud) bloc ×10
flutter ×10
dart ×3
flutter-bloc ×1
hierarchical ×1
navigation ×1
nested ×1
rxdart ×1
stream ×1
testing ×1
websocket ×1