【问题标题】:Event added to Bloc and yield state but it not recall bloc builder将事件添加到 Bloc 和 yield 状态,但它不召回 bloc builder
【发布时间】:2021-03-01 03:47:47
【问题描述】:

当我使用 BlocProvider.of 从无状态小部件添加事件时,它确实添加了事件和屈服状态,BlocBuilder 工作并更改 UI,

但是,当从一个单独的类中添加一个事件时,它确实将一个事件添加到了 bloc 中,onTransition 工作,但不会产生新的状态,BlocBuilder 不能改变 UI。

主要:

main(){
return runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
 MQTTManager x = MQTTManager();
 return MaterialApp(
   home: BlocProvider(
     lazy: false,
     create:(context)=>MqttblocBloc(MQTTManager())..add(StartConnect()) ,
     child:Home() ,
   ),
 );
}
}

集团:

class MqttblocBloc extends Bloc<MqttblocEvent, MqttblocState> {
  MQTTManager manager = MQTTManager() ;
  MqttblocBloc(this.manager) : super(MqttblocInitial());

 @override
 Stream<MqttblocState> mapEventToState(
   MqttblocEvent event,
 ) async* {
   if(event is StartConnect){
    try{
      manager.initializeMQTTClient();
      manager.connect();
      yield MqttblocInitial();
    }catch(e){
      print(e);
    }
   }

   else if(event is ConnectedEvent) {
     try{
       print('inBloc connect....');
       yield ConnectedState(MQTTManager.s);
     }catch(e){
       print(e);
     }
   }


   else if(event is PublishedEvent){
     try{
       manager.publishsw1('on');
       print('inBloc publish........');
       yield PublishState(manager.getText1());
     }catch(e){
       print(e);
     }
   }

   else if(event is DisconnectedEvent) {
     try{
       print('inBloc And Disconnnnn....');
       yield DisconnectState(MQTTManager.u);
     }catch(e){
       print(e);
     }
   }

 }
 @override
 void onTransition(Transition<MqttblocEvent, MqttblocState> transition) {
   super.onTransition(transition);
   print(transition);
 }
}

这里是我监听服务器并向 bloc 添加事件的单独类:

class MQTTManager {

  MqttblocBloc bloc ;

  static var s ;
  static var u ;
  MqttServerClient client;
  String text ;
  String text1 ;
  String text2 ;
  static List<String> conn = [] ;

  void initializeMQTTClient(){
    client = MqttServerClient("broker.shiftr.io","User");
    client.port = 1883;
    
    client.secure = false;
    client.logging(on: true);
    client.onConnected = onConnected;

    final MqttConnectMessage connMess = MqttConnectMessage()
        .authenticateAs('889514b9', 'd5459e3f6b0422cb')
        .withClientIdentifier("User")
        .withWillTopic('willtopic') 
        .withWillMessage('My Will message')
        .startClean() // Non persistent session for testing
        .withWillQos(MqttQos.atLeastOnce);
    print('EXAMPLE::Mosquitto client connecting....');
    client.connectionMessage = connMess;

  }
  // Connect to the host
  void connect() async{
    assert(client != null);
    try {
      print('EXAMPLE::Mosquitto start client connecting....');
      await client.connect();
      Amar(); // <...... here calling this fun to start listen to Server
    } on Exception catch (e) {
      print('EXAMPLE::client exception - $e');
      disconnect();
    }
  }

  void disconnect() {
    print('Disconnected');
    client.disconnect();
  }

  void publishsw1(String message){
    final MqttClientPayloadBuilder builder = MqttClientPayloadBuilder();
    builder.addString(message);
    client.publishMessage('hello/sw1', MqttQos.exactlyOnce, builder.payload);

  }
  void onConnected() {

    print('EXAMPLE::shiftr client connected....');

    client.subscribe("hello/sw1", MqttQos.atLeastOnce);

    client.updates.listen((List<MqttReceivedMessage<MqttMessage>> c) {
      final MqttPublishMessage recMess = c[0].payload;
      final String pt =
      MqttPublishPayload.bytesToStringAsString(recMess.payload.message);
      setText(pt);

    });

  }

   Amar() { //<....... here h listen to server 
     bloc =  MqttblocBloc(this);
     client.subscribe("\$events", MqttQos.atLeastOnce);

    client.updates.listen((List<MqttReceivedMessage<MqttMessage>> c) {
      final MqttPublishMessage recMess = c[0].payload;
      final String pt =
      MqttPublishPayload.bytesToStringAsString(recMess.payload.message);

      var z =  DetectEvent.fromJson(json.decode(pt));
      if(z.type == 'connected'){
        var connected = Connected.fromJson(json.decode(pt));
        print (connected.type);
        bloc.add(ConnectedEvent()); // <... here I add event to Bloc , but it not changeing UI  

      }
      else if(z.type == 'disconnected'){
        var disconnected = Disconnected.fromJson(json.decode(pt));
        print (disconnected.type) ;
        bloc.add(DisconnectedEvent()); // <... here I add event to Bloc , but it not changeing UI  

      }
      else if(z.type == 'published'){
        var published = Published.fromJson(json.decode(pt));
        print(published.type) ;
      }
}
}

这是一个无状态小部件并使用 blocbuider :

class Home extends StatelessWidget {
MQTTManager v = MQTTManager();
  @override
  Widget build(BuildContext context) {
    MqttblocBloc p = BlocProvider.of<MqttblocBloc>(context);
    return Scaffold(
      appBar: AppBar(
        title: Text('Bloc MQTT'),
        actions: [
          Row(
            children: [
              IconButton(
                icon: Icon(Icons.wb_incandescent,
                ),
                onPressed: (){
                 p.add(PublishedEvent());//<.... here it change UI ,
                },
              ),
            ],
          )
        ],
      ),
      body: Center(
        child: BlocBuilder<MqttblocBloc,MqttblocState>(
         // buildWhen: (previuosState , currentState)=>currentState.runtimeType !=previuosState.runtimeType,

          builder:(context , state){
            if(state is MqttblocInitial){
              return CircularProgressIndicator();
            }
            else if(state is ConnectedState){
              return IconButton(
                icon: Icon(Icons.wifi),
                onPressed: (){},
              );
            }
            else if(state is PublishState){
              return RaisedButton(
                child: Text('${state.x}'),
                onPressed: (){},
              );
            }
            else if(state is DisconnectState){
              return IconButton(
                icon: Icon(Icons.wb_incandescent),
                onPressed: (){
                },
              );
            }
            return CircularProgressIndicator();
          } ,
        ),
      )
    );
  }
}

集团状态:

@immutable
abstract class MqttblocState extends Equatable {
 const MqttblocState();
  @override
  List<Object> get props => [];

}

class MqttblocInitial extends MqttblocState {}

class ConnectedState extends MqttblocState{
  final String x ;
  ConnectedState(this.x);
  @override
  List<Object> get props => [x];
}
class PublishState extends MqttblocState{
  final String x ;
  PublishState(this.x);
  @override
  List<Object> get props => [x];
}

class DisconnectState extends MqttblocState{
  final String x ;
  DisconnectState(this.x);
  @override
  List<Object> get props => [x];
}

和集体活动

@immutable
abstract class MqttblocEvent extends Equatable  {
  MqttblocEvent();
  @override
  List<Object> get props => [];
}

class StartConnect extends MqttblocEvent{}

class ConnectedEvent extends MqttblocEvent{}

class PublishedEvent extends MqttblocEvent{}

class DisconnectedEvent extends MqttblocEvent{}


【问题讨论】:

  • 不确定,但您是否创建了该集团的第二个实例?在这种情况下,您必须将 bloc 实例作为参数传递
  • 其中 bloc 的第二个实例,只需在 Amar() 函数中使用它,即可接收来自服务器的事件以将该事件添加到 bloc ,并且该事件实际上转换为状态和过渡工作,但不重建与状态相对应的用户界面......我希望能帮助PLZ

标签: flutter bloc


【解决方案1】:

这就是为什么,您产生了相同的状态并使用 Equatable 没有任何不同的道具进行比较,因此 BlocBuilder 没有看到任何变化。

你有两个解决方案 ether un-inherit Equatable from class MqttblocEvent

 abstract class MqttblocEvent {
  MqttblocEvent();
}

或在中间产生不同的状态,例如 MqrrblocInProgress(推荐):

 Stream<MqttblocState> mapEventToState(
   MqttblocEvent event,
 ) async* {
    yield MqrrblocInProgress();
.....

【讨论】:

  • 感谢重播,但同样的问题仍然存在..我已经尝试了很多,如果解决了会很高兴
  • 如果可以的话,你能解释一下吗?
【解决方案2】:

再次发送相同的状态时,UI 不会重建。您需要先发送一些其他状态。因此,对于任何事件,您的映射应如下所示:

if(event is StartConnect){
    yield MqrrblocInProgress(); // <============== ADDED
    try{
      manager.initializeMQTTClient();
      manager.connect();
      yield MqttblocInitial();
    }catch(e){
      print(e);
    }

当然,你也需要定义这个状态(InProgress),以及在 UI 中为这个状态定义一些小部件(例如纺车)

【讨论】:

  • 同样的问题仍然存在,我添加其他状态并产生它到目前为止每个事件并为该状态定义小部件,我将向你展示转换:I/flutter (29067): Transition { currentState: 'MqttblocInitial' 实例,事件:'ConnectedEvent' 实例,nextState:'MqttInProgress' 实例',事件:'ConnectedEvent'的实例,nextState:'ConnectedState'的实例}
  • 如果可以的话,你能解释一下吗?
  • 你在阿马尔初始化你的集团。我猜,Home 不是 Amar 的子小部件。所以它可能找不到它。尝试将 MqttblocBloc bloc = MqttblocBloc(this); 放入 MyApp 并将其传递给小部件,或者 - 像你一样 - 使用 MqttblocBloc p = BlocProvider.of&lt;MqttblocBloc&gt;(context);
  • 也不起作用,我认为您已经解决了主要问题,因为 Home 有上下文,MqttblocBloc p = BlocProvider.of&lt;MqttblocBloc&gt;(**context**); 上下文是小部件树的引用,我可以在其中添加到 Bloc 并更改UI,但 Amar() 是某个类中的一个函数,该类不是小部件树的子类来访问 UI 并更改它,所以如果我从 Home 将事件添加到 Bloc 它真的会重建 UI,但是如果我将事件添加到来自 Amar() 的 Bloc,UI 没有响应并且永远不会改变,请注意即使我从 Amar() 向 Bloc 添加事件,转换也可以正确工作。
  • 那么您应该尝试将 bloc 作为参数传递给 Amar。实际上,如果这是完整的代码,Amar 对我来说更像是一个函数。
猜你喜欢
  • 2020-05-06
  • 2023-01-05
  • 2020-07-21
  • 2021-03-19
  • 2022-10-06
  • 2020-03-26
  • 1970-01-01
  • 2020-04-29
  • 2022-11-24
相关资源
最近更新 更多