Flutter Bloc add 事件只为同一个小部件触发一次,不会再次触发

时间:2020-12-19 11:46:16

标签: flutter bloc flutter-bloc

我是 Bloc 的新手(来自提供者),一切正常,除非我尝试将第二个事件添加到同一个小部件上的同一个 bloc,它永远不会被触发,即使 mapEventToState 也不会触发,

我首先添加一个事件以在 initState 中获取帖子,这很好用,稍后我在刷新指示器 onRefresh 函数上添加事件,该函数内的所有内容都会触发,除了 bloc 添加事件。

我正在使用 Equatable,所以我尝试不使用它,但没有区别。 我试图为每个州创建单独的类,但仍然无法正常工作。 我试着不要在处置时关闭集团,也没有工作。

ForumMain 小部件是 BottomNavigationTabBar 的子项

这是我的代码: ma​​in.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 未能为每个州创建单独的类

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) {

2 个答案:

答案 0 :(得分:0)

请像这样更改您的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 :(得分:0)

您可以尝试将提供者列表放在 _blocProviders() 中,而不是 MultiBlocProvider( providers: [ ... ],

我明白了。请尝试删除以下代码。我认为你不应该在这个小部件中关闭它,因为这不是你初始化它的地方。

_forumBloc.close();
_planBloc.close();