Flutter Bloc добавляет событие, которое запускается только один раз для одного и того же виджета и больше не запускается

#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