flutter - Flutter BlocBuilder 构建器仅在最初被调用并且不对状态更改做出反应
问题描述
我最近才开始使用 Flutter。BLoC 确实有一个陡峭的学习曲线......
从标题中可以清楚地看出,BlocBuilder 逻辑仅在应用程序启动时正确执行一次。然而,之后,UI 不会在状态更改时重建。尽管所有事件都会被发出,并且状态会发生变化。
提前感谢您的帮助!
这是我的'main.dart':
import 'package:co_flutter/auth/authentication_bloc.dart';
import 'package:co_flutter/auth/authentication_event.dart';
import 'package:co_flutter/auth/authentication_state.dart';
import 'package:co_flutter/auth/login/login_bloc.dart';
import 'package:co_flutter/auth/signup/signup_page.dart';
import 'package:co_flutter/loading_indicator.dart';
import 'package:co_flutter/splash_page.dart';
import 'package:co_flutter/user_repository.dart';
import 'package:flutter/material.dart';
import 'package:bloc/bloc.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'auth/login/login_page.dart';
class SimpleBlocObserver extends BlocObserver {
@override
void onCreate(BlocBase bloc) {
super.onCreate(bloc);
print('onCreate -- ${bloc.runtimeType}');
}
@override
void onEvent(Bloc bloc, Object? event) {
super.onEvent(bloc, event);
print('onEvent -- ${bloc.runtimeType}, $event');
}
@override
void onTransition(Bloc bloc, Transition transition) {
super.onTransition(bloc, transition);
print('onTransition -- ${bloc.runtimeType}, $transition');
}
@override
void onChange(BlocBase bloc, Change change) {
super.onChange(bloc, change);
print('onChange -- ${bloc.runtimeType}, $change');
}
@override
void onError(BlocBase bloc, Object error, StackTrace stackTrace) {
print('onError -- ${bloc.runtimeType}, $error');
super.onError(bloc, error, stackTrace);
}
@override
void onClose(BlocBase bloc) {
super.onClose(bloc);
print('onClose -- ${bloc.runtimeType}');
}
}
void main() {
Bloc.observer = SimpleBlocObserver();
runApp(MyApp(
userRepository: UserRepository(),
));
}
class MyApp extends StatefulWidget {
final UserRepository userRepository;
MyApp({Key? key, required this.userRepository}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late AuthenticationBloc authenticationBloc;
UserRepository get userRepository => widget.userRepository;
@override
void initState() {
authenticationBloc = AuthenticationBloc(userRepository: userRepository);
authenticationBloc.add(AppStarted());
super.initState();
}
@override
void dispose() {
authenticationBloc.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<AuthenticationBloc>(
create: (BuildContext context) => authenticationBloc,
),
BlocProvider<LoginBloc>(
create: (BuildContext context) => LoginBloc(
userRepository: userRepository,
authenticationBloc: authenticationBloc),
),
],
child: MaterialApp(
title: 'My App',
theme: ThemeData(
primarySwatch: Colors.indigo,
),
home: BlocBuilder<AuthenticationBloc, AuthenticationState>(
builder: (BuildContext context, AuthenticationState state) {
if (state is AuthenticationUninitialized) {
return SplashPage();
}
if (state is AuthenticationAuthenticated) {
return Dashboard(
title: 'Dashboard',
);
}
if (state is AuthenticationUnauthenticated) {
return LoginPage(
userRepository: userRepository,
);
}
if (state is AuthenticationLoading) {
return LoadingIndicator();
}
// else {
// return Text('Error');
// }
return BlocBuilder<LoginBloc, LoginState>(
builder: (context, state) {
if (state is LoginToSignup) {
return SignUpPage();
} else
return SizedBox.shrink();
},
);
},
),
),
);
}
}
class Dashboard extends StatelessWidget {
final String title;
const Dashboard({Key? key, required this.title}) : super(key: key);
@override
Widget build(BuildContext context) {
final AuthenticationBloc authenticationBloc =
BlocProvider.of<AuthenticationBloc>(context);
return Scaffold(
appBar: AppBar(
title: Text('Dashboard'),
),
body: Container(
child: Center(
child: ElevatedButton(
child: Text('logout'),
onPressed: () {
authenticationBloc.add(LoggedOut());
},
),
),
),
);
}
}
身份验证块
import 'dart:async';
import 'package:co_flutter/auth/authentication_event.dart';
import 'package:co_flutter/auth/authentication_state.dart';
import 'package:bloc/bloc.dart';
import '../user_repository.dart';
class AuthenticationBloc
extends Bloc<AuthenticationEvent, AuthenticationState> {
UserRepository userRepository;
AuthenticationBloc({required this.userRepository})
: super(AuthenticationUninitialized()) {
userRepository = UserRepository();
}
@override
Stream<AuthenticationState> mapEventToState(
AuthenticationEvent event,
) async* {
if (event is AppStarted) {
final bool hasToken = await userRepository.hasToken();
if (hasToken) {
yield AuthenticationAuthenticated();
} else {
yield AuthenticationUnauthenticated();
}
}
if (event is LoggedIn) {
yield AuthenticationLoading();
await userRepository.persistToken(event.token, event.userId);
yield AuthenticationAuthenticated();
}
if (event is LoggedOut) {
yield AuthenticationLoading();
await userRepository.deleteToken();
yield AuthenticationUnauthenticated();
}
}
}
身份验证事件
import 'package:equatable/equatable.dart';
abstract class AuthenticationEvent extends Equatable {
@override
List<Object> get props => [];
}
class AppStarted extends AuthenticationEvent {
@override
String toString() => 'AppStarted';
}
class LoggedIn extends AuthenticationEvent {
final String token;
final String userId;
LoggedIn({required this.token, required this.userId});
@override
String toString() => 'LoggedIn { token: $token}';
}
class LoggedOut extends AuthenticationEvent {
@override
String toString() => 'LoggedOut';
}
身份验证状态
import 'package:equatable/equatable.dart';
abstract class AuthenticationState extends Equatable {
const AuthenticationState();
}
class AuthenticationUninitialized extends AuthenticationState {
@override
List<Object> get props => [];
}
class AuthenticationLoading extends AuthenticationState {
@override
List<Object> get props => [];
}
class AuthenticationAuthenticated extends AuthenticationState {
@override
List<Object> get props => [];
}
class AuthenticationUnauthenticated extends AuthenticationState {
@override
List<Object> get props => [];
}
解决方案
问题就在这里。您已经创建了一个集团:
authenticationBloc = AuthenticationBloc(userRepository: userRepository);
在这里,您正在尝试再次创建它。
要修复它,请替换此代码:
BlocProvider<AuthenticationBloc>(
create: (BuildContext context) => authenticationBloc,
),
有了这个:
BlocProvider<AuthenticationBloc>.value(
value: authenticationBloc,
),
将 bloc 传递给 bloc builder
BlocBuilder<AuthenticationBloc, AuthenticationState>(
bloc: authenticationBloc,
在 dispose 函数中使用 bloc authenticationBloc 后,不要忘记对其进行 dispose。
推荐阅读
- mongodb - MongoDB $addFields 使用 org.springframework.data.mongodb.core.MongoTemplate
- python - 大型 JSON 文件读取、替换和写入
- c# - 重新创建位图图像 URI
- rabbitmq - 阻止 MassTransit 为消费者主机创建 RabbitMQ 交换
- python - 使用 PyPDF2 通过 python 加密许多 PDF
- excel - 双击工作表中的任何单元格运行宏
- java - 使用前增量器的 Java 加法会根据使用括号给出不同的结果
- react-native - React Native 中的 clipsToBounds
- android - 如何将 productFlavors 用于 android aab 捆绑包
- azure-devops - Azure Devops 部署 Azure C# 函数