flutter_bloc: ^6.1.1 未更改状态
flutter_bloc: ^6.1.1 not changing state
我正在使用 flutter_bloc: ^6.1.1 以及依赖注入 get_it: ^5.0.6。当我向 bloc 提交事件时,状态没有改变。
nav_bar_bloc.dart
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:dartz/dartz.dart';
import 'package:equatable/equatable.dart';
import 'package:meta/meta.dart';
import '../../../../../core/error/failures.dart';
import '../../../../../core/usecases/usecase.dart';
import '../../../domain/entities/fixtures_entities.dart';
import '../../../domain/entities/prediction_entities.dart';
import '../../../domain/usecases/get_fixtures.dart';
import '../../../domain/usecases/get_predictions.dart';
part 'nav_bar_event.dart';
part 'nav_bar_state.dart';
const String SERVER_FAILURE_MESSAGE = 'SERVER FAILURE. TRY AGAIN LATER';
const String CACHE_FAILURE_MESSAGE = 'CACHE FAILURE';
class NavBarBloc extends Bloc<NavBarEvent, NavBarState> {
final GetBasicFixtures getBasicFixtures;
final GetPredictions getPredictions;
NavBarBloc({
@required this.getBasicFixtures,
@required this.getPredictions,
}) : super(NavBarInitialState());
@override
Stream<NavBarState> mapEventToState(
NavBarEvent event,
) async* {
print(event);
// FIXTURES EVENT
// yield HomePageLoadingState();
if (event is HomePageSelectEvent) {
Either<Failure, List<BasicFixturesEntity>> response =
await getBasicFixtures(NoParams());
yield* response.fold((failure) async* {
yield HomePageLoadFailureState(message: _mapFailureToMessage(failure));
}, (fixtures) async* {
print(fixtures[0].away);
yield HomePageLoadSuccessState(fixtures: fixtures);
});
} // GET PREDICTIONS EVENT
else if (event is PredictionPageSelectEvent) {
yield PredictionPageLoadingState();
Either<Failure, List<PredictionEntity>> response =
await getPredictions(NoParams());
yield* response.fold((failure) async* {
yield PredictionPageLoadFailureState(
message: _mapFailureToMessage(failure));
}, (predictions) async* {
yield PredictionPageLoadSuccessState(predictions: predictions);
});
} // NEWS EVENT
else if (event is NewsPageSelectEvent) {
yield NewsPageLoadingState();
yield NewsPageLoadSuccessState();
} // ACCOUNT EVENT
else if (event is AccountPageSelectEvent) {
yield AccountPageLoadingState();
yield AccountPageLoadSuccessState();
}
}
String _mapFailureToMessage(Failure failure) {
switch (failure.runtimeType) {
case ServerFailure:
return SERVER_FAILURE_MESSAGE;
case CacheFailure:
return CACHE_FAILURE_MESSAGE;
default:
return 'UNEXPECTED ERROR';
}
}
}
nav_bar_event.dart
part of 'nav_bar_bloc.dart';
abstract class NavBarEvent extends Equatable {
const NavBarEvent();
@override
List<Object> get props => [];
}
class HomePageSelectEvent extends NavBarEvent {}
class PredictionPageSelectEvent extends NavBarEvent {}
class NewsPageSelectEvent extends NavBarEvent {}
class AccountPageSelectEvent extends NavBarEvent {}
nav_bar_state.dart
part of 'nav_bar_bloc.dart';
abstract class NavBarState extends Equatable {
const NavBarState();
@override
List<Object> get props => [];
}
class NavBarInitialState extends NavBarState {}
// Initial HOME PAGE [FIXTURES PAGE]
class HomePageLoadingState extends NavBarState {}
class HomePageLoadSuccessState extends NavBarState {
final List<BasicFixturesEntity> fixtures;
HomePageLoadSuccessState({@required this.fixtures});
@override
List<Object> get props => [fixtures];
}
class HomePageLoadFailureState extends NavBarState {
final String message;
HomePageLoadFailureState({@required this.message});
@override
List<Object> get props => [message];
}
// PREDICTION PAGE
class PredictionPageLoadingState extends NavBarState {}
class PredictionPageLoadSuccessState extends NavBarState {
final List<PredictionEntity> predictions;
PredictionPageLoadSuccessState({@required this.predictions});
@override
List<Object> get props => [predictions];
}
class PredictionPageLoadFailureState extends NavBarState {
final String message;
PredictionPageLoadFailureState({@required this.message});
@override
List<Object> get props => [message];
}
// NEWS PAGE
class NewsPageLoadingState extends NavBarState {}
class NewsPageLoadSuccessState extends NavBarState {}
class NewsPageLoadFailureState extends NavBarState {}
// ACCOUNT PAGE
class AccountPageLoadingState extends NavBarState {}
class AccountPageLoadSuccessState extends NavBarState {}
class AccountPageLoadailureState extends NavBarState {}
ui.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../../injection_containers/injection_container.dart';
import '../bloc/nav_bar_bloc/nav_bar_bloc.dart';
import '../widgets/core/navbar.dart';
import 'account_page/account_page.dart';
import 'fixtures_page/fixtures_page.dart';
import 'news_page/news_page.dart';
import 'prediction_page/prediction_page.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
void initState() {
super.initState();
sl<NavBarBloc>().add(HomePageSelectEvent());
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
bottomSheet: NavBar(),
body: BlocProvider(
create: (_) => sl<NavBarBloc>(),
child:
// ignore: missing_return
BlocBuilder<NavBarBloc, NavBarState>(builder: (context, state) {
print(state);
// HOME PAGE aka. FIXTURES PAGE
if (state is HomePageLoadFailureState) {
return Center(child: Text(state.message));
} else if (state is HomePageLoadSuccessState) {
return FixturesPage(fixtures: state.fixtures);
} else if (state is HomePageLoadingState) {
return Center(child: CircularProgressIndicator());
}
// PREDICTION PAGE
else if (state is PredictionPageLoadingState) {
return Center(child: CircularProgressIndicator());
} else if (state is PredictionPageLoadFailureState) {
return Center(child: Text(state.message));
} else if (state is PredictionPageLoadSuccessState) {
return PredictionPage(predictions: state.predictions);
}
// ACCOUNT PAGE
else if (state is AccountPageLoadingState) {
return AccountPage();
} else if (state is AccountPageLoadSuccessState) {
return AccountPage();
} else if (state is AccountPageLoadailureState) {
return AccountPage();
}
// NEWS PAGE
else if (state is NewsPageLoadingState) {
return NewsPage();
} else if (state is NewsPageLoadSuccessState) {
return NewsPage();
} else if (state is NewsPageLoadFailureState) {
return NewsPage();
} else if (state is NavBarInitialState) {
return Center(
child: Text(
"loading",
style: TextStyle(color: Colors.white),
));
}
})));
}
}
dependency_injection.dart
import 'package:connectivity/connectivity.dart';
import 'package:get_it/get_it.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
import '../core/network/network_info.dart';
import '../features/predictor/data/datasources/local_data_source/fixtures_local_data_source.dart';
import '../features/predictor/data/datasources/local_data_source/prediction_local_data_source.dart';
import '../features/predictor/data/datasources/remote_data_source/fixtures_remote_data_source.dart';
import '../features/predictor/data/datasources/remote_data_source/prediction_remote_data_source.dart';
import '../features/predictor/data/datasources/token_access.dart';
import '../features/predictor/data/repositories/fixtures_repositories_impl.dart';
import '../features/predictor/data/repositories/prediction_repositories_impl.dart';
import '../features/predictor/domain/repositories/fixtures_repositories.dart';
import '../features/predictor/domain/repositories/prediction_repositories.dart';
import '../features/predictor/domain/usecases/get_fixtures.dart';
import '../features/predictor/domain/usecases/get_predictions.dart';
import '../features/predictor/domain/usecases/submit_prediction.dart';
import '../features/predictor/presentation/bloc/nav_bar_bloc/nav_bar_bloc.dart';
import '../features/predictor/presentation/bloc/prediction_submit_bloc/prediction_submit_bloc.dart';
GetIt sl = GetIt.instance;
Future<void> init() async {
// NavBarBloc
sl.registerFactory<NavBarBloc>(
() => NavBarBloc(getBasicFixtures: sl(), getPredictions: sl()));
// SubmitPredictionBloc
sl.registerFactory<PredictionSubmitBloc>(
() => PredictionSubmitBloc(submitPrediction: sl()));
// Validate token
sl.registerLazySingleton<ValidateToken>(() => ValidateTokenImpl());
/// usecase
///
// Fixtures
sl.registerLazySingleton(() => GetBasicFixtures(repository: sl()));
// Get-predictions
sl.registerLazySingleton(() => GetPredictions(repository: sl()));
// submit-prediction
sl.registerLazySingleton(() => SubmitPrediction(predictionRepository: sl()));
/// repository
///
// Fixtures
sl.registerLazySingleton<BasicFixturesRepository>(() =>
BasicFixturesRepositoryImpl(
localDataSource: sl(), networkInfo: sl(), remoteDataSource: sl()));
// Prediction
sl.registerLazySingleton<PredictionRepository>(() => PredictionRepositoryImpl(
localDataSource: sl(), networkInfo: sl(), remoteDataSource: sl()));
/// Data Source
/// Remote Date Source
///
// Fixtures
sl.registerLazySingleton<BasicFixturesRemoteDataSource>(() =>
BasicFixturesRemoteDataSourceImpl(client: sl(), validateToken: sl()));
// Prediction
sl.registerLazySingleton<PredictionsRemoteDataSource>(
() => PredictionsRemoteDataSourceImpl(client: sl(), validateToken: sl()));
/// Local Data Source
///
// Fixtures
sl.registerLazySingleton<BasicFixturesLocalDataSource>(
() => BasicFixturesLocalDataSourceImpl(sharedPreferences: sl()));
// Prediction
sl.registerLazySingleton<PredictionsLocalDataSource>(
() => PredictionLocalDataSourceImpl(sharedPreferences: sl()));
// External
sl.registerLazySingleton<NetworkInfo>(() => NetworkInfoImpl(sl()));
final sharedPreferences = await SharedPreferences.getInstance();
sl.registerLazySingleton(() => sharedPreferences);
sl.registerLazySingleton(() => http.Client());
sl.registerLazySingleton(() => Connectivity());
}
一切正常,除了 bloc 没有改变它的状态。它停留在初始状态。代码在向服务器发出 API 请求时正常工作。
问题是你注册了NavBarBloc
工厂。因此,每当您调用 sl<NavBarBloc>()
时,都会创建一个新的 bloc 实例。
因此,当您调用 sl<NavBarBloc>().add(HomePageSelectEvent())
时,事件将添加到另一个实例,而不是您传递给 bloc builder 的实例。
更新:
两个简短的例子:
- 使用
BlocProvider
:
...
BlocProvider(
create: (_) => sl<NavBarBloc>()..add(add(HomePageSelectEvent()),
...
)
...
- 正在您的小部件中保存实例:
...
NavBarBloc navBarBloc;
@override
void initState() {
super.initState();
navBarBloc = sl<NavBarBloc>()..add(HomePageSelectEvent());
}
@override
void dispose() {
navBarBloc.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
bottomSheet: NavBar(),
body: BlocProvider.value(
value: navBarBloc,
...
我正在使用 flutter_bloc: ^6.1.1 以及依赖注入 get_it: ^5.0.6。当我向 bloc 提交事件时,状态没有改变。
nav_bar_bloc.dart
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:dartz/dartz.dart';
import 'package:equatable/equatable.dart';
import 'package:meta/meta.dart';
import '../../../../../core/error/failures.dart';
import '../../../../../core/usecases/usecase.dart';
import '../../../domain/entities/fixtures_entities.dart';
import '../../../domain/entities/prediction_entities.dart';
import '../../../domain/usecases/get_fixtures.dart';
import '../../../domain/usecases/get_predictions.dart';
part 'nav_bar_event.dart';
part 'nav_bar_state.dart';
const String SERVER_FAILURE_MESSAGE = 'SERVER FAILURE. TRY AGAIN LATER';
const String CACHE_FAILURE_MESSAGE = 'CACHE FAILURE';
class NavBarBloc extends Bloc<NavBarEvent, NavBarState> {
final GetBasicFixtures getBasicFixtures;
final GetPredictions getPredictions;
NavBarBloc({
@required this.getBasicFixtures,
@required this.getPredictions,
}) : super(NavBarInitialState());
@override
Stream<NavBarState> mapEventToState(
NavBarEvent event,
) async* {
print(event);
// FIXTURES EVENT
// yield HomePageLoadingState();
if (event is HomePageSelectEvent) {
Either<Failure, List<BasicFixturesEntity>> response =
await getBasicFixtures(NoParams());
yield* response.fold((failure) async* {
yield HomePageLoadFailureState(message: _mapFailureToMessage(failure));
}, (fixtures) async* {
print(fixtures[0].away);
yield HomePageLoadSuccessState(fixtures: fixtures);
});
} // GET PREDICTIONS EVENT
else if (event is PredictionPageSelectEvent) {
yield PredictionPageLoadingState();
Either<Failure, List<PredictionEntity>> response =
await getPredictions(NoParams());
yield* response.fold((failure) async* {
yield PredictionPageLoadFailureState(
message: _mapFailureToMessage(failure));
}, (predictions) async* {
yield PredictionPageLoadSuccessState(predictions: predictions);
});
} // NEWS EVENT
else if (event is NewsPageSelectEvent) {
yield NewsPageLoadingState();
yield NewsPageLoadSuccessState();
} // ACCOUNT EVENT
else if (event is AccountPageSelectEvent) {
yield AccountPageLoadingState();
yield AccountPageLoadSuccessState();
}
}
String _mapFailureToMessage(Failure failure) {
switch (failure.runtimeType) {
case ServerFailure:
return SERVER_FAILURE_MESSAGE;
case CacheFailure:
return CACHE_FAILURE_MESSAGE;
default:
return 'UNEXPECTED ERROR';
}
}
}
nav_bar_event.dart
part of 'nav_bar_bloc.dart';
abstract class NavBarEvent extends Equatable {
const NavBarEvent();
@override
List<Object> get props => [];
}
class HomePageSelectEvent extends NavBarEvent {}
class PredictionPageSelectEvent extends NavBarEvent {}
class NewsPageSelectEvent extends NavBarEvent {}
class AccountPageSelectEvent extends NavBarEvent {}
nav_bar_state.dart
part of 'nav_bar_bloc.dart';
abstract class NavBarState extends Equatable {
const NavBarState();
@override
List<Object> get props => [];
}
class NavBarInitialState extends NavBarState {}
// Initial HOME PAGE [FIXTURES PAGE]
class HomePageLoadingState extends NavBarState {}
class HomePageLoadSuccessState extends NavBarState {
final List<BasicFixturesEntity> fixtures;
HomePageLoadSuccessState({@required this.fixtures});
@override
List<Object> get props => [fixtures];
}
class HomePageLoadFailureState extends NavBarState {
final String message;
HomePageLoadFailureState({@required this.message});
@override
List<Object> get props => [message];
}
// PREDICTION PAGE
class PredictionPageLoadingState extends NavBarState {}
class PredictionPageLoadSuccessState extends NavBarState {
final List<PredictionEntity> predictions;
PredictionPageLoadSuccessState({@required this.predictions});
@override
List<Object> get props => [predictions];
}
class PredictionPageLoadFailureState extends NavBarState {
final String message;
PredictionPageLoadFailureState({@required this.message});
@override
List<Object> get props => [message];
}
// NEWS PAGE
class NewsPageLoadingState extends NavBarState {}
class NewsPageLoadSuccessState extends NavBarState {}
class NewsPageLoadFailureState extends NavBarState {}
// ACCOUNT PAGE
class AccountPageLoadingState extends NavBarState {}
class AccountPageLoadSuccessState extends NavBarState {}
class AccountPageLoadailureState extends NavBarState {}
ui.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../../injection_containers/injection_container.dart';
import '../bloc/nav_bar_bloc/nav_bar_bloc.dart';
import '../widgets/core/navbar.dart';
import 'account_page/account_page.dart';
import 'fixtures_page/fixtures_page.dart';
import 'news_page/news_page.dart';
import 'prediction_page/prediction_page.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
void initState() {
super.initState();
sl<NavBarBloc>().add(HomePageSelectEvent());
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
bottomSheet: NavBar(),
body: BlocProvider(
create: (_) => sl<NavBarBloc>(),
child:
// ignore: missing_return
BlocBuilder<NavBarBloc, NavBarState>(builder: (context, state) {
print(state);
// HOME PAGE aka. FIXTURES PAGE
if (state is HomePageLoadFailureState) {
return Center(child: Text(state.message));
} else if (state is HomePageLoadSuccessState) {
return FixturesPage(fixtures: state.fixtures);
} else if (state is HomePageLoadingState) {
return Center(child: CircularProgressIndicator());
}
// PREDICTION PAGE
else if (state is PredictionPageLoadingState) {
return Center(child: CircularProgressIndicator());
} else if (state is PredictionPageLoadFailureState) {
return Center(child: Text(state.message));
} else if (state is PredictionPageLoadSuccessState) {
return PredictionPage(predictions: state.predictions);
}
// ACCOUNT PAGE
else if (state is AccountPageLoadingState) {
return AccountPage();
} else if (state is AccountPageLoadSuccessState) {
return AccountPage();
} else if (state is AccountPageLoadailureState) {
return AccountPage();
}
// NEWS PAGE
else if (state is NewsPageLoadingState) {
return NewsPage();
} else if (state is NewsPageLoadSuccessState) {
return NewsPage();
} else if (state is NewsPageLoadFailureState) {
return NewsPage();
} else if (state is NavBarInitialState) {
return Center(
child: Text(
"loading",
style: TextStyle(color: Colors.white),
));
}
})));
}
}
dependency_injection.dart
import 'package:connectivity/connectivity.dart';
import 'package:get_it/get_it.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
import '../core/network/network_info.dart';
import '../features/predictor/data/datasources/local_data_source/fixtures_local_data_source.dart';
import '../features/predictor/data/datasources/local_data_source/prediction_local_data_source.dart';
import '../features/predictor/data/datasources/remote_data_source/fixtures_remote_data_source.dart';
import '../features/predictor/data/datasources/remote_data_source/prediction_remote_data_source.dart';
import '../features/predictor/data/datasources/token_access.dart';
import '../features/predictor/data/repositories/fixtures_repositories_impl.dart';
import '../features/predictor/data/repositories/prediction_repositories_impl.dart';
import '../features/predictor/domain/repositories/fixtures_repositories.dart';
import '../features/predictor/domain/repositories/prediction_repositories.dart';
import '../features/predictor/domain/usecases/get_fixtures.dart';
import '../features/predictor/domain/usecases/get_predictions.dart';
import '../features/predictor/domain/usecases/submit_prediction.dart';
import '../features/predictor/presentation/bloc/nav_bar_bloc/nav_bar_bloc.dart';
import '../features/predictor/presentation/bloc/prediction_submit_bloc/prediction_submit_bloc.dart';
GetIt sl = GetIt.instance;
Future<void> init() async {
// NavBarBloc
sl.registerFactory<NavBarBloc>(
() => NavBarBloc(getBasicFixtures: sl(), getPredictions: sl()));
// SubmitPredictionBloc
sl.registerFactory<PredictionSubmitBloc>(
() => PredictionSubmitBloc(submitPrediction: sl()));
// Validate token
sl.registerLazySingleton<ValidateToken>(() => ValidateTokenImpl());
/// usecase
///
// Fixtures
sl.registerLazySingleton(() => GetBasicFixtures(repository: sl()));
// Get-predictions
sl.registerLazySingleton(() => GetPredictions(repository: sl()));
// submit-prediction
sl.registerLazySingleton(() => SubmitPrediction(predictionRepository: sl()));
/// repository
///
// Fixtures
sl.registerLazySingleton<BasicFixturesRepository>(() =>
BasicFixturesRepositoryImpl(
localDataSource: sl(), networkInfo: sl(), remoteDataSource: sl()));
// Prediction
sl.registerLazySingleton<PredictionRepository>(() => PredictionRepositoryImpl(
localDataSource: sl(), networkInfo: sl(), remoteDataSource: sl()));
/// Data Source
/// Remote Date Source
///
// Fixtures
sl.registerLazySingleton<BasicFixturesRemoteDataSource>(() =>
BasicFixturesRemoteDataSourceImpl(client: sl(), validateToken: sl()));
// Prediction
sl.registerLazySingleton<PredictionsRemoteDataSource>(
() => PredictionsRemoteDataSourceImpl(client: sl(), validateToken: sl()));
/// Local Data Source
///
// Fixtures
sl.registerLazySingleton<BasicFixturesLocalDataSource>(
() => BasicFixturesLocalDataSourceImpl(sharedPreferences: sl()));
// Prediction
sl.registerLazySingleton<PredictionsLocalDataSource>(
() => PredictionLocalDataSourceImpl(sharedPreferences: sl()));
// External
sl.registerLazySingleton<NetworkInfo>(() => NetworkInfoImpl(sl()));
final sharedPreferences = await SharedPreferences.getInstance();
sl.registerLazySingleton(() => sharedPreferences);
sl.registerLazySingleton(() => http.Client());
sl.registerLazySingleton(() => Connectivity());
}
一切正常,除了 bloc 没有改变它的状态。它停留在初始状态。代码在向服务器发出 API 请求时正常工作。
问题是你注册了NavBarBloc
工厂。因此,每当您调用 sl<NavBarBloc>()
时,都会创建一个新的 bloc 实例。
因此,当您调用 sl<NavBarBloc>().add(HomePageSelectEvent())
时,事件将添加到另一个实例,而不是您传递给 bloc builder 的实例。
更新: 两个简短的例子:
- 使用
BlocProvider
:
...
BlocProvider(
create: (_) => sl<NavBarBloc>()..add(add(HomePageSelectEvent()),
...
)
...
- 正在您的小部件中保存实例:
...
NavBarBloc navBarBloc;
@override
void initState() {
super.initState();
navBarBloc = sl<NavBarBloc>()..add(HomePageSelectEvent());
}
@override
void dispose() {
navBarBloc.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
bottomSheet: NavBar(),
body: BlocProvider.value(
value: navBarBloc,
...