Bloc的值未更新

时间:2019-12-17 10:06:07

标签: flutter dart

所以我有这个结构

  1. MainPage()-> CustomAppBar();
  2. NotificationPage()-> BuildNotificationList();

他们两个都使用相同的Bloc NotificationBLoc()

class NotificationBLoc extends Bloc<NotificationEvent, NotificationState> {
  @override
  NotificationState get initialState => InitialNotification();

  @override
  Stream<NotificationState> mapEventToState(NotificationEvent event) async* {
    final currentState = state;
    if (event is FetchNotification && !_hasReachedMax(currentState)) {
      try {
        if (currentState is InitialNotification) {
          yield LoadNotification();
          final posts = await fetchNotification(0, 10, event.userId);
          yield NotificationLoaded(notif: posts, hasReachedMax: false);
          return;
        }
        if (currentState is NotificationLoaded) {
          final posts = await fetchNotification(
              currentState.notif.length, 10, event.userId);

          yield posts.isEmpty
              ? currentState.copyWith(hasReachedMax: true)
              : NotificationLoaded(
                  notif: currentState.notif + posts,
                  hasReachedMax: false,
                );
        }
      } catch (e) {
        print(e.toString());
        yield NotificationError();
      }
    }

    if (event is OpenNotification) {
      if (currentState is NotificationLoaded) {
        currentState.notif[event.notificationIndex].notificationFlag = "1";
        List<Notif> filteredRecored = new List<Notif>();
        currentState.notif.forEach((r) {
          filteredRecored.add(r);
        });

        yield NotificationLoaded(notif: filteredRecored, hasReachedMax: false);
      }
    }
  }

  bool _hasReachedMax(NotificationState state) =>
      state is NotificationLoaded && state.hasReachedMax;

  Future<List<Notif>> fetchNotification(
      int limit, int offset, String userId) async {
    final response = await http.Client().post(
        Configuration.url +
            "api/getNotification/" +
            limit.toString() +
            "/" +
            offset.toString() +
            "/",
        body: {"userId": userId});

    if (response.statusCode < 200 || response.statusCode > 300) {
      throw new Exception('Failed to fetch data');
    } else {
      List<dynamic> responseData = jsonDecode(response.body);
      final List<Notif> notif = [];
      responseData.forEach((singleChild) {
        notif.add(
          Notif(
            notificationId: singleChild['notificationId'],
            notificationTitle: singleChild['notificationTitle'],
            notificationBody: singleChild['notificationBody'],
            notificationDate: singleChild['notificationDate'],
            notificationTo: singleChild['notificationTo'],
            notificationImage: singleChild['notificationImage'],
            notificationFlag: singleChild['notificationFlag'],
          ),
        );
      });
      return notif;
    }
  }
}

在第一个结构中(在CustomAppBar内部),我这样做

notificationBLoc.add(FetchNotification(userId: userId));

这是CustomAppBar内部使用Bloc的

BlocBuilder<NotificationBLoc, NotificationState>(
            builder: (context, state) {
              if (state is NotificationLoaded) {
                List<Notif> filteredRecored = new List<Notif>();
                state.notif.forEach((f) {
                  if (f.notificationFlag.toLowerCase().contains("0") ||
                      f.notificationFlag.contains("0")) {
                      filteredRecored.add(f);
                  }
                });
                print(filteredRecored.length.toString());
                return new Stack(
                  children: <Widget>[
                    new IconButton(
                      icon: Icon(
                        Icons.notifications,
                        color: Colors.brown,
                      ),
                      onPressed: () {
                        Navigator.push(
                          context,
                          MaterialPageRoute(
                              builder: (context) => NotificationPage()),
                        );
                      },
                    ),
                    filteredRecored.length != 0
                        ? new Positioned(
                            right: 7,
                            top: 5,
                            child: new Container(
                              decoration: new BoxDecoration(
                                color: Colors.red,
                                borderRadius: BorderRadius.circular(6),
                              ),
                              constraints: BoxConstraints(
                                minWidth: 15,
                                minHeight: 15,
                              ),
                              child: Text(
                                filteredRecored.length.toString(),
                                style: TextStyle(
                                  color: Colors.white,
                                  fontSize: 11,
                                ),
                                textAlign: TextAlign.center,
                              ),
                            ),
                          )
                        : new Container(),
                  ],
                );
              } else {
                return Container(
                  child: null,
                );
              }
            },
          ),

它显示6(总计数据)。

然后我执行此操作以在第二个结构中获取数据

notificationBLoc = BlocProvider.of<NotificationBLoc>(context);
notificationBLoc.add(FetchNotification(userId: userId));

数据显示的与我期望的一样,然后从列表中单击一个。那个刺激

 notificationBLoc.add(OpenNotification(notificationIndex: index));

因此它将运行

if (event is OpenNotification) {
  if (currentState is NotificationLoaded) {
    currentState.notif[event.notificationIndex].notificationFlag = "1";
    List<Notif> filteredRecored = new List<Notif>();
    currentState.notif.forEach((r) {
      filteredRecored.add(r);
    });

    yield NotificationLoaded(notif: filteredRecored, hasReachedMax: false);
  }
}

因此,在第一个结构中,数据长度仍然是6,而不是5。当我重新打开应用程序时,数据长度变成5。

我想念什么吗?

这是我的Bloc状态

abstract class NotificationState extends Equatable {
  const NotificationState();

  @override
  List<Object> get props => [];
}

class InitialNotification extends NotificationState {}

class LoadNotification extends NotificationState {}



class NotificationLoaded extends NotificationState {
  final List<Notif> notif;
  final bool hasReachedMax;

  const NotificationLoaded({
    this.notif,
    this.hasReachedMax,
  });

  NotificationLoaded copyWith({
    List<Notif> notif,
    bool hasReachedMax,
  }) {
    return NotificationLoaded(
      notif: notif ?? this.notif,
      hasReachedMax: hasReachedMax ?? this.hasReachedMax,
    );
  }

  @override
  List<Object> get props => [notif, hasReachedMax];
}

class NotificationError extends NotificationState {
  String message;

  NotificationError({@required this.message});

  @override
  List<Object> get props => [message];
}

这是我的Notif课

class Notif extends Equatable {
  final String notificationId;
  final String notificationTitle;
  final String notificationBody;
  final String notificationDate;
  final String notificationTo;
  final String notificationImage;
  String notificationFlag;

  Notif(
      {this.notificationId,
      this.notificationTitle,
      this.notificationBody,
      this.notificationDate,
      this.notificationTo,
      this.notificationImage,
      this.notificationFlag});

  factory Notif.fromJson(Map<dynamic, dynamic> json) {
    return Notif(
      notificationId: json['notificationId'] as String,
      notificationTitle: json['notificationTitle'] as String,
      notificationBody: json['notificationBody'] as String,
      notificationDate: json['notificationDate'] as String,
      notificationTo: json['notificationTo'] as String,
      notificationImage: json['notificationImage'] as String,
      notificationFlag: json['notificationFlag'] as String,
    );
  }

  bool operator ==(o) => o is Notif && notificationId == o.notificationId;

  int get hashCode => notificationId.hashCode;
}

因此,我将有两个notificationFlag 0或1(均为字符串,这很不好)。因此,在我的CustomAppBar()中(第一个结构)。我这样做(如下)来读取Notif的列表中有1个为notificationFlag

state.notif.forEach((f) {
                  if (f.notificationFlag.toLowerCase().contains("0") ||
                      f.notificationFlag.contains("0")) {
                      filteredRecored.add(f);
                  }
                });

对不起,我的英语水平

1 个答案:

答案 0 :(得分:0)

这个答案可能是错误的,但是可能将blocEquatable一起使用?如果是这样,请确保使用Equatable扩展所有事件和状态,并正确覆盖props

@override
List<Object> get props => // Add all the properties of your event or state here

在开发过程中,我发生了很多事情,状态不是由集团触发的。这是由于bloc跳过了“相同”状态的事实。因此,您需要正确实现Equatable,以使集团知道您的属性之一实际上是不同的。

例如:

class NotificationLoaded extends Equatable {
  final String oneOfYourProperties;

  const NotificationLoaded(this.oneOfYourProperties);

  @override
  List<Object> get props => [this.oneOfYourProperties];
}

编辑:

在这里,我为您提供了如何在Equatable中正确实现Notif的实现。我认为operatorhashcode声明引起了一些问题。请尝试将您的Notif代码替换为以下内容:

class Notif extends Equatable {
  final String notificationId;
  final String notificationTitle;
  final String notificationBody;
  final String notificationDate;
  final String notificationTo;
  final String notificationImage;
  String notificationFlag;

  Notif(
      {this.notificationId,
      this.notificationTitle,
      this.notificationBody,
      this.notificationDate,
      this.notificationTo,
      this.notificationImage,
      this.notificationFlag});

  factory Notif.fromJson(Map<dynamic, dynamic> json) {
    return Notif(
      notificationId: json['notificationId'] as String,
      notificationTitle: json['notificationTitle'] as String,
      notificationBody: json['notificationBody'] as String,
      notificationDate: json['notificationDate'] as String,
      notificationTo: json['notificationTo'] as String,
      notificationImage: json['notificationImage'] as String,
      notificationFlag: json['notificationFlag'] as String,
    );
  }

  @override
  List<Object> get props => [
      this.notificationId,
      this.notificationTitle,
      this.notificationBody,
      this.notificationDate,
      this.notificationTo,
      this.notificationImage,
      this.notificationFlag];
}