#flutter #bloc #flutter-bloc
#flutter #блок #flutter-bloc
Вопрос:
Я новичок в блоке (от поставщика), все работает нормально, за исключением того, что всякий раз, когда я пытаюсь добавить второе событие в тот же блок в том же виджете, оно никогда не срабатывает, даже mapEventToState не срабатывает,
сначала я добавляю событие для получения сообщений в initState, это работает нормально, позже я добавляю событие для индикатора обновления в функцию onRefresh, все внутри функции срабатывает, кроме события добавления блока.
Я использую Equatable, поэтому я попробовал без него и без разницы. я пытался создать отдельный класс для каждого состояния, но все равно не работает. я пытался не закрывать блок при удалении, также не работает.
Виджет ForumMain является дочерним элементом BottomNavigationTabBar
вот мой код: main.dart
List<BlocProvider<Bloc>> _blocProviders() => [
BlocProvider<UserBloc>(
create: (context) => UserBloc(userRepository: RepositoryProvider.of(context),navigator: RepositoryProvider.of(context),prefs: RepositoryProvider.of(context),
),
),
BlocProvider<ForumBloc>(
create: (context) => ForumBloc( RepositoryProvider.of(context),_userBloc, RepositoryProvider.of(context),),
),
BlocProvider<WUpdateBloc>(
create: (context) => WUpdateBloc(
RepositoryProvider.of(context),
RepositoryProvider.of(context)),
),
BlocProvider<PlanBloc>(
create: (context) => PlanBloc(RepositoryProvider.of(context),RepositoryProvider.of(context),
)),
];
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
return OrientationBuilder(builder: (context, orientation) {
return RepositoryProvider(
create: (context) => _dioInstance(),
child: MultiRepositoryProvider(
providers: _repositoryProviders(),
child: MultiBlocProvider(
providers: _blocProviders(),
child: Builder(
builder: (context) => MaterialApp(
// theme: AppTheme.theme,
navigatorKey: navigatorKey,
navigatorObservers: [appNavigatorObserver],
localizationsDelegates: _getLocalizationsDelegates(),
supportedLocales: S.delegate.supportedLocales,
home: LoadingPage(),
debugShowCheckedModeBanner: false,
),
)),
),
);
});
});
}
forum_bloc.dart
class ForumBloc extends Bloc<ForumEvent, ForumState> {
ForumBloc(this._forumRepository, this._userBloc, this.navigator) : super(ForumState.defaultState());
final ForumRepository _forumRepository;
final UserBloc _userBloc;
final AppNavigator navigator;
@override
Stream<ForumState> mapEventToState(
ForumEvent event,
) async* {
if (event is GetPostsEvent) yield* _getPosts(event);
if (event is GetCommentsEvent) yield* _getComments(event);
if (event is RefreshPostsEvent) yield* _refreshPosts(event);
if (event is RefreshCommentsEvent) yield* _refreshComments(event);
if (event is NewPostRequest) yield* _newPost(event);
if (event is NewCommentRequest) yield* _newComment(event);
}
Stream<ForumState> _getPosts(GetPostsEvent event) async* {
print("get posts event called");
yield state.copyWith(status: BlocStatus.pending);
try {
// show progress hud
final postsResponse = await _forumRepository.getPosts(event.trainerID);
postsResponse.posts.sort((a, b) => b.datetimeCreated.compareTo(a.datetimeCreated));
print(postsResponse.posts[0].question);
yield state.copyWith(posts: postsResponse.posts, status: BlocStatus.success, total: postsResponse.posts.length);
} on DioError catch (error) {
// report error
yield state.copyWith(status: BlocStatus.error, appError: error.toAppError());
}
}
Stream<ForumState> _refreshPosts(RefreshPostsEvent event) async* {
print("refresh posts event called");
try {
// show progress hud
final postsResponse = await _forumRepository.getPosts(event.trainerID);
print(postsResponse.posts.length);
postsResponse.posts.sort((a, b) => b.datetimeCreated.compareTo(a.datetimeCreated));
yield state.copyWith(posts: postsResponse.posts, status: BlocStatus.success, total: postsResponse.posts.length);
} on DioError catch (error) {
// report error
// yield state.copyWith(status: BlocStatus.error, appError: error.toAppError());
}
}
forum_state.dart
class ForumState extends Equatable {
ForumState({
this.total,
this.posts,
this.status,
this.appError
});
final int total;
final List<BlogPost> posts;
final BlocStatus status;
final AppError appError;
factory ForumState.defaultState() => ForumState(
total: 0,
posts: [],
status: BlocStatus.idle,
appError: null
);
ForumState copyWith({
int total,
List<BlogPost> posts,
AppError appError,
BlocStatus status, }) { return ForumState(
total: total ?? this.total,
posts: posts ?? this.posts,
status: status,
);}
@override
List<Object> get props => [posts,total,status,appError];
@override
bool get stringify => true;
}
forum_state.dart failed trial to make separate class for each state
class ForumState extends Equatable {
@override
// TODO: implement props
List<Object> get props => [];
}
class ForumStateLoading extends ForumState {
}
class ForumStateSuccess extends ForumState {
ForumStateSuccess({
this.total,
this.posts,
});
final int total;
final List<BlogPost> posts;
@override
List<Object> get props => [posts,total];
}
class ForumStateRefresh extends ForumState {
ForumStateRefresh({
this.total,
this.posts,
});
final int total;
final List<BlogPost> posts;
@override
List<Object> get props => [posts,total];
}
class ForumStateError extends ForumState {
ForumStateError({
this.error,
});
final AppError error;
@override
List<Object> get props => [error];
}
forum_event.dart
abstract class ForumEvent extends Equatable {
const ForumEvent();
@override
List<Object> get props => [];
}
class GetPostsEvent extends ForumEvent {
final String trainerID;
GetPostsEvent(this.trainerID);
}
class RefreshPostsEvent extends ForumEvent {
final String trainerID;
RefreshPostsEvent(this.trainerID);
}
class GetCommentsEvent extends ForumEvent {
final String postID;
final String trainerID;
GetCommentsEvent(this.postID,this.trainerID);
}
class RefreshCommentsEvent extends ForumEvent {
final String postID;
final String trainerID;
RefreshCommentsEvent(this.postID,this.trainerID);
}
class SendPostEvent extends ForumEvent {
final NewPostRequest postRequest;
SendPostEvent(this.postRequest);
}
class SendCommentEvent extends ForumEvent {
final NewCommentRequest commentRequest;
SendCommentEvent(this.commentRequest);
}
forum_screen.dart
class ForumMain extends StatefulWidget {
@override
_ForumMainState createState() => _ForumMainState();
}
class _ForumMainState extends State<ForumMain> {
TextEditingController nameController = TextEditingController();
MyTheme myTheme = MyTheme();
ForumBloc _forumBloc;
PlanBloc _planBloc;
Completer<void> _refreshCompleter;
@override
void initState() {
// TODO: implement initState
super.initState();
myTheme.initLoadingHUD();
_forumBloc = BlocProvider.of<ForumBloc>(context);
_planBloc = BlocProvider.of<PlanBloc>(context);
_forumBloc.add(GetPostsEvent(_planBloc.state.chosenOrder.trainer.id));
_refreshCompleter = Completer<void>();
}
@override
void dispose() {
_forumBloc.close();
_planBloc.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
ScreenUtil.init(context, width: 375, height: 812, allowFontScaling: true);
return BlocConsumer<ForumBloc,ForumState>(
listener: (context, state) {
print(state.status.toString());
setState(() {
_refreshCompleter?.complete();
_refreshCompleter = Completer();
});
myTheme.errorBlocListener(context, state.appError);
},
cubit: _forumBloc,
builder: (context, state) {
return Scaffold(
backgroundColor: Colors.white,
appBar: ForumAppBar(
height: 80.h,
forum: true,
),
body: state.status == BlocStatus.success ? Stack(
children: [
RefreshIndicator(
onRefresh: () {
_forumBloc.add(RefreshPostsEvent(
_planBloc.state.chosenOrder.trainer.id));
return _refreshCompleter.future;
},
child: ListView(
children: state.posts.map((e) {
Ответ №1:
Пожалуйста, измените ваш файл forum_event следующим образом:
abstract class ForumEvent extends Equatable {
const ForumEvent([List props = const []]) : super();
}
class GetPostsEvent extends ForumEvent {
final String trainerID;
GetPostsEvent(this.trainerID);
@override
List<Object> get props => [trainerID];
}
class RefreshPostsEvent extends ForumEvent {
final String trainerID;
RefreshPostsEvent(this.trainerID);
@override
List<Object> get props => [trainerID];
}
class GetCommentsEvent extends ForumEvent {
final String postID;
final String trainerID;
GetCommentsEvent(this.postID,this.trainerID);
@override
List<Object> get props => [postID, trainerID];
}
class RefreshCommentsEvent extends ForumEvent {
final String postID;
final String trainerID;
RefreshCommentsEvent(this.postID,this.trainerID);
@override
List<Object> get props => [postID, trainerID];
}
class SendPostEvent extends ForumEvent {
final NewPostRequest postRequest;
SendPostEvent(this.postRequest);
@override
List<Object> get props => [postRequest];
}
class SendCommentEvent extends ForumEvent {
final NewCommentRequest commentRequest;
SendCommentEvent(this.commentRequest);
@override
List<Object> get props => [commentRequest];
}
Комментарии:
1. эй, спасибо за ваш ответ, я знаю, что должен был добавить реквизит, но это ничего не изменило, я пробовал это и все еще НЕ работает!
Ответ №2:
Вы можете попробовать вместо _blocProviders()
того, чтобы просто размещать список поставщиков внутри MultiBlocProvider( providers: [ ... ],
.
Я вижу. Пожалуйста, попробуйте удалить следующий код. Я не думаю, что вам следует закрывать его в этом виджете, поскольку вы не инициализируете его здесь.
_forumBloc.close();
_planBloc.close();
Комментарии:
1. Пожалуйста, попробуйте удалить команды .close() в dispose.
2. хм, наверное, лучше всего поделиться репозиторием git для этого, чтобы я мог взглянуть и провести некоторый тест.
3. кроме того, есть ли у вас какое-либо сообщение об ошибке при выполнении обновления?
4. проблема в том, что я не получаю никаких ошибок! это так странно, и теперь у меня такая же проблема в другом виджете, поэтому RefreshIndicator не является причиной проблемы, отправьте мне сообщение, если вы хотите взглянуть на репозиторий git