【问题标题】:Flutter Bloc add event triggers only once for the same widget and won't trigger againFlutter Bloc 只为同一个小部件添加事件触发一次,并且不会再次触发
【发布时间】:2021-03-29 20:13:17
【问题描述】:

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

我首先在 initState 中添加一个事件来获取帖子,这工作正常,稍后我在刷新指示器 onRefresh 函数上添加事件,函数内的所有内容都会触发,除了 bloc add 事件。

我正在使用 Equatable,所以我尝试不使用它并且没有区别。 我试图为每个州单独上课,但仍然无法正常工作。 我试图在 dispose 时不关闭该集团,也无法正常工作。

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

【问题讨论】:

    标签: flutter bloc flutter-bloc


    【解决方案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];
       }
    

    【讨论】:

    • 嘿,谢谢你的回答,我知道我应该添加道具,但它没有改变任何东西,我试过了,但还是不行!
    【解决方案2】:

    您可以尝试代替_blocProviders(),只需将提供者列表放入MultiBlocProvider( providers: [ ... ],

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

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

    【讨论】:

    • 请尝试删除 dispose 中的 .close() 命令。
    • hmm,可能最好为此分享 git repo,以便我可以查看并进行一些测试。
    • 另外,您在刷新时是否有任何错误消息?
    • 问题是我没有得到任何错误!太奇怪了,现在我在另一个小部件中遇到了同样的问题,所以 RefreshIndicator 不是问题的原因,如果您愿意查看 git repo,请给我发消息
    猜你喜欢
    • 2022-01-01
    • 2015-12-04
    • 1970-01-01
    • 2020-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多