handledOnUpdate method

  1. @protected
Future<void> handledOnUpdate(
  1. ModelUpdateNotification update
)

Describe the callback process to pass to ModelAdapterCollectionQuery.callback.

This is executed when there is a change in the associated collection or document.

Please take appropriate action according to the contents of update.

ModelAdapterCollectionQuery.callbackに渡すためのコールバック処理を記述します。

関連するコレクションやドキュメントに変更があった場合、こちらが実行されます。

updateの内容に応じて適切な処理を行ってください。

Implementation

@protected
Future<void> handledOnUpdate(ModelUpdateNotification update) async {
  // 確実に後続の処理が実行されるようにした
  try {
    if (update.query != modelQuery) {
      return;
    }
    // Aggregationの処理
    for (final entry in _aggregate.entries) {
      entry.key.onUpdate(update, entry.value);
    }
    var notify = false;
    switch (update.status) {
      case ModelUpdateNotificationStatus.added:
        if (update.newIndex == null) {
          return;
        }
        // indexの位置がおかしい場合は無視
        if (_value.length < update.newIndex!) {
          return;
        }
        // すでに追加されているのに追加でデータが来た場合は無視
        if (this._value.any((e) => e.uid == update.id)) {
          return;
        }
        final value = create(update.id.trimQuery().trimString("?"));
        final val = value.value;
        final filtered =
            value.filterOnLoad(ModelFieldValue.fromMap(update.value));
        if (filtered.isEmpty) {
          value._value = null;
          // 最初にいれないと要素が無いエラーがでる場合がある
          _value.insert(update.newIndex!, value);
        } else {
          final fromMap = value._value = value.fromMap(filtered);
          // 最初にいれないと要素が無いエラーがでる場合がある
          _value.insert(update.newIndex!, value);
          value._value = await value.filterOnDidLoad(fromMap);
        }
        if (val != value.value) {
          value.notifyListeners();
        }
        notify = true;
        break;
      case ModelUpdateNotificationStatus.modified:
        if (update.oldIndex == null || update.newIndex == null) {
          return;
        }
        // indexの位置がおかしい場合は無視
        if (_value.length <= update.oldIndex! ||
            _value.length < update.newIndex!) {
          return;
        }
        // 指定位置に違うデータが来た場合は無視
        final found = _value[update.oldIndex!];
        if (found.uid != update.id) {
          return;
        }
        final val = found.value;
        final filtered =
            found.filterOnLoad(ModelFieldValue.fromMap(update.value));
        if (filtered.isEmpty) {
          found._value = null;
          // 削除と挿入は同時に行わないと不具合が発生する
          _value.removeAt(update.oldIndex!);
          // 最初にいれないと要素が無いエラーがでる場合がある
          _value.insert(update.newIndex!, found);
        } else {
          final fromMap = found._value = found.fromMap(filtered);
          // 削除と挿入は同時に行わないと不具合が発生する
          _value.removeAt(update.oldIndex!);
          // 最初にいれないと要素が無いエラーがでる場合がある
          _value.insert(update.newIndex!, found);
          found._value = await found.filterOnDidLoad(fromMap);
        }
        if (val != found.value) {
          found.notifyListeners();
        }
        // ここにいれないと更新されないことがある
        if (modelQuery.filters.any(
            (e) => e.type == ModelQueryFilterType.notifyDocumentChanges)) {
          notify = true;
        }
        if (update.newIndex != update.oldIndex) {
          notify = true;
        }
        break;
      case ModelUpdateNotificationStatus.removed:
        if (update.oldIndex == null) {
          return;
        }
        // indexの位置がおかしい場合は無視
        if (_value.length <= update.oldIndex!) {
          return;
        }
        // すでに削除されているのに削除でデータが来た場合は無視
        if (!this._value.any((e) => e.uid == update.id)) {
          return;
        }
        _value.removeAt(update.oldIndex!);
        notify = true;
        break;
    }
    if (notify) {
      notifyListeners();
    }
  } catch (e, s) {
    debugPrint("$e\n$s");
  }
}