繁体   English   中英

Flutter 从其他集团听集团 state

[英]Flutter listen Bloc state from Other Bloc

您好,我正在尝试收听 state of bloc form other bloc。 我正在使用这个 package https://pub.dev/packages/bloc

从我的UserBloc我想听AuthBloc ,当它有 state AuthenticationAuthenticated时, UserBloc应该触发一个事件。

final UserRepository userRepository;
final authBloc;
StreamSubscription authSub;
UserBloc({ @required this.userRepository, @required this.authBloc}) {
    authSub = authBloc.listen((stateAuth) {

      //here is my problem because stateAuth, even is AuthenticationAuthenticated it return always false.
      if (stateAuth is AuthenticationAuthenticated) {
        this.add(GetUser())  ;
      }
    });
  }

@override
  Future<void> close() async {
    authSub?.cancel();
    super.close();
  }

现在我有这个问题:在调试时我试图打印 stateAuth 它返回:

stateAuth = {AuthenticationAuthenticated} AuthenticationAuthenticated
   props = {_ImmutableList} size = 0

但是stateAuth 是 AuthenticationAuthenticated返回总是 false。

有什么办法可以从其他 Bloc class 监听 blocState 吗?

要回答 Sampir 的问题,是的,您是对的,但有时您可能想以另一种方式来回答。 集团是为其他人管理事件的东西。 如果您正在使用 ui 事件,您的 bloc 会为您的 ui 管理它们,但如果您还使用其他类型的事件(即位置事件或其他流事件),您可以有一个 bloc 来管理您的 ui 事件和另一个 bloc管理其他类型的事件(即蓝牙连接)。 所以第一个块必须听第二个(即因为正在等待建立蓝牙连接)。 考虑一个使用大量传感器的应用程序,每个传感器都有其数据流,您将拥有一系列必须合作的集团。 您可以使用多提供者和多侦听器来做到这一点,但是您的链可能很长,并且编写您的侦听器案例可能很困难,或者您可能希望将其隐藏在您的 ui 中,或者您想在您的另一部分重用它应用程序,因此您可能希望在您的集团内建立您的链。

您几乎可以在任何地方将侦听器添加到 bloc。 使用 StreamSubscription,您可以为每种类型的流添加侦听器,甚至是另一个块中的流。 该集团必须有一种方法来公开他的流,这样你就可以听他的了。

一些代码(我使用 flutter_bloc - flutter_bloc 有多个提供者,但这只是示例):

class BlocA extends Bloc<EventA, StateA> {

  final BlocB blocB;
  StreamSubscription subscription;

  BlocA({this.blocB}) {
    if (blocB == null) return;
    subscription = blocB.listen((stateB) {
      //here logic based on different children of StateB
    });
  }

  //...

}

class BlocB extends Bloc<EventB, StateB> {
   //here BlocB logic and activities
}

实际上,在bloc 库的一个示例中,他们从另一个 Bloc (FilteredTodosBloc) 监听一个 Bloc (TodosBloc)。

class FilteredTodosBloc extends Bloc<FilteredTodosEvent, FilteredTodosState> {
  final TodosBloc todosBloc;
  StreamSubscription todosSubscription;

  FilteredTodosBloc({@required this.todosBloc}) {
    todosSubscription = todosBloc.listen((state) {
      if (state is TodosLoadSuccess) {
        add(TodosUpdated((todosBloc.state as TodosLoadSuccess).todos));
      }
    });
  }
...

您可以在此处查看此示例的说明。

bloc 源代码的最新更新需要对解决方案进行小幅更改。

你现在必须听一个 bloc/cubit 的流属性,请看下面的例子。

class FilteredTodosBloc extends Bloc<FilteredTodosEvent, FilteredTodosState> {
  final TodosBloc todosBloc;
  StreamSubscription todosSubscription;

  FilteredTodosBloc({@required this.todosBloc}) {
    todosSubscription = todosBloc.stream.listen((state) {
    //                             ^^^^^
      if (state is TodosLoadSuccess) {
        add(TodosUpdated((todosBloc.state as TodosLoadSuccess).todos));
      }
    });
  }
...

对于那些仍在寻找的人(尤其是最佳实践的人),您可能不希望您的 bloc 依赖于具有直接 bloc-to-bloc 依赖关系的另一个 bloc,而是您可能希望通过表示层连接您的 bloc。 例如:

class MyWidget extends StatelessWidget {
  const MyWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocListener<WeatherCubit, WeatherState>(
      listener: (context, state) {
        // When the first bloc's state changes, this will be called.
        //
        // Now we can add an event to the second bloc without it having
        // to know about the first bloc.
        BlocProvider.of<SecondBloc>(context).add(SecondBlocEvent());
      },
      child: TextButton(
        child: const Text('Hello'),
        onPressed: () {
          BlocProvider.of<FirstBloc>(context).add(FirstBlocEvent());
        },
      ),
    );
  }
}

请查看官方文档以获取更多信息。

对于不想扰乱集团的人,

我们可以使用这个库Event Bus 它基于 stream。我们可以从屏幕之间的任何位置触发和监听事件。

// declare this globally

EventBus eventBus = EventBus();


// create event
class UserLoggedInEvent {
  User user;

  UserLoggedInEvent(this.user);
}


// listen event
eventBus.on<UserLoggedInEvent>().listen((event) {
  // All events are of type UserLoggedInEvent (or subtypes of it).
  print(event.user);
});


// fire event
User myUser = User('Mickey');
eventBus.fire(UserLoggedInEvent(myUser));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM