浏览代码

chore: refactor rowbloc

appflowy 3 年之前
父节点
当前提交
f40e0c18e6
共有 23 个文件被更改,包括 185 次插入173 次删除
  1. 5 5
      frontend/app_flowy/lib/startup/deps_resolver.dart
  2. 2 2
      frontend/app_flowy/lib/workspace/application/grid/cell/cell_service.dart
  3. 3 3
      frontend/app_flowy/lib/workspace/application/grid/cell/checkbox_cell_bloc.dart
  4. 3 3
      frontend/app_flowy/lib/workspace/application/grid/cell/date_cell_bloc.dart
  5. 3 3
      frontend/app_flowy/lib/workspace/application/grid/cell/number_cell_bloc.dart
  6. 3 3
      frontend/app_flowy/lib/workspace/application/grid/cell/selection_cell_bloc.dart
  7. 2 2
      frontend/app_flowy/lib/workspace/application/grid/cell/selection_editor_bloc.dart
  8. 4 4
      frontend/app_flowy/lib/workspace/application/grid/cell/text_cell_bloc.dart
  9. 7 3
      frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart
  10. 43 0
      frontend/app_flowy/lib/workspace/application/grid/grid_service.dart
  11. 11 67
      frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart
  12. 80 55
      frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart
  13. 1 5
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart
  14. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart
  15. 2 2
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_container.dart
  16. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart
  17. 2 2
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell.dart
  18. 2 2
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart
  19. 4 4
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart
  20. 2 2
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart
  21. 2 2
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart
  22. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/cell/number_cell.dart
  23. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/number_cell.dart

+ 5 - 5
frontend/app_flowy/lib/startup/deps_resolver.dart

@@ -168,32 +168,32 @@ void _resolveGridDeps(GetIt getIt) {
     ),
   );
 
-  getIt.registerFactoryParam<TextCellBloc, GridCellIdentifier, void>(
+  getIt.registerFactoryParam<TextCellBloc, GridCell, void>(
     (cellData, _) => TextCellBloc(
       service: CellService(),
       cellData: cellData,
     ),
   );
 
-  getIt.registerFactoryParam<SelectionCellBloc, GridCellIdentifier, void>(
+  getIt.registerFactoryParam<SelectionCellBloc, GridCell, void>(
     (cellData, _) => SelectionCellBloc(
       cellData: cellData,
     ),
   );
 
-  getIt.registerFactoryParam<NumberCellBloc, GridCellIdentifier, void>(
+  getIt.registerFactoryParam<NumberCellBloc, GridCell, void>(
     (cellData, _) => NumberCellBloc(
       cellData: cellData,
     ),
   );
 
-  getIt.registerFactoryParam<DateCellBloc, GridCellIdentifier, void>(
+  getIt.registerFactoryParam<DateCellBloc, GridCell, void>(
     (cellData, _) => DateCellBloc(
       cellIdentifier: cellData,
     ),
   );
 
-  getIt.registerFactoryParam<CheckboxCellBloc, GridCellIdentifier, void>(
+  getIt.registerFactoryParam<CheckboxCellBloc, GridCell, void>(
     (cellData, _) => CheckboxCellBloc(
       service: CellService(),
       cellData: cellData,

+ 2 - 2
frontend/app_flowy/lib/workspace/application/grid/cell/cell_service.dart

@@ -44,7 +44,7 @@ class CellCache {
 
   CellCache() : _cellService = CellService();
 
-  Future<Option<Cell>> getCellData(GridCellIdentifier identifier) async {
+  Future<Option<Cell>> getCellData(GridCell identifier) async {
     final cellId = _cellId(identifier);
     final Cell? data = _cellDataMap[cellId];
     if (data != null) {
@@ -69,7 +69,7 @@ class CellCache {
     );
   }
 
-  String _cellId(GridCellIdentifier identifier) {
+  String _cellId(GridCell identifier) {
     return "${identifier.rowId}/${identifier.field.id}";
   }
 }

+ 3 - 3
frontend/app_flowy/lib/workspace/application/grid/cell/checkbox_cell_bloc.dart

@@ -15,7 +15,7 @@ class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
 
   CheckboxCellBloc({
     required CellService service,
-    required GridCellIdentifier cellData,
+    required GridCell cellData,
   })  : _service = service,
         _listener = CellListener(rowId: cellData.rowId, fieldId: cellData.field.id),
         super(CheckboxCellState.initial(cellData)) {
@@ -87,11 +87,11 @@ class CheckboxCellEvent with _$CheckboxCellEvent {
 @freezed
 class CheckboxCellState with _$CheckboxCellState {
   const factory CheckboxCellState({
-    required GridCellIdentifier cellData,
+    required GridCell cellData,
     required bool isSelected,
   }) = _CheckboxCellState;
 
-  factory CheckboxCellState.initial(GridCellIdentifier cellData) {
+  factory CheckboxCellState.initial(GridCell cellData) {
     return CheckboxCellState(cellData: cellData, isSelected: _isSelected(cellData.cell));
   }
 }

+ 3 - 3
frontend/app_flowy/lib/workspace/application/grid/cell/date_cell_bloc.dart

@@ -15,7 +15,7 @@ class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
   final CellListener _cellListener;
   final SingleFieldListener _fieldListener;
 
-  DateCellBloc({required GridCellIdentifier cellIdentifier})
+  DateCellBloc({required GridCell cellIdentifier})
       : _service = CellService(),
         _cellListener = CellListener(rowId: cellIdentifier.rowId, fieldId: cellIdentifier.field.id),
         _fieldListener = SingleFieldListener(fieldId: cellIdentifier.field.id),
@@ -106,13 +106,13 @@ class DateCellEvent with _$DateCellEvent {
 @freezed
 class DateCellState with _$DateCellState {
   const factory DateCellState({
-    required GridCellIdentifier cellData,
+    required GridCell cellData,
     required String content,
     required Field field,
     DateTime? selectedDay,
   }) = _DateCellState;
 
-  factory DateCellState.initial(GridCellIdentifier cellData) => DateCellState(
+  factory DateCellState.initial(GridCell cellData) => DateCellState(
         cellData: cellData,
         field: cellData.field,
         content: cellData.cell?.content ?? "",

+ 3 - 3
frontend/app_flowy/lib/workspace/application/grid/cell/number_cell_bloc.dart

@@ -16,7 +16,7 @@ class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
   final SingleFieldListener _fieldListener;
 
   NumberCellBloc({
-    required GridCellIdentifier cellData,
+    required GridCell cellData,
   })  : _service = CellService(),
         _cellListener = CellListener(rowId: cellData.rowId, fieldId: cellData.field.id),
         _fieldListener = SingleFieldListener(fieldId: cellData.field.id),
@@ -105,11 +105,11 @@ class NumberCellEvent with _$NumberCellEvent {
 @freezed
 class NumberCellState with _$NumberCellState {
   const factory NumberCellState({
-    required GridCellIdentifier cellData,
+    required GridCell cellData,
     required String content,
   }) = _NumberCellState;
 
-  factory NumberCellState.initial(GridCellIdentifier cellData) {
+  factory NumberCellState.initial(GridCell cellData) {
     return NumberCellState(cellData: cellData, content: cellData.cell?.content ?? "");
   }
 }

+ 3 - 3
frontend/app_flowy/lib/workspace/application/grid/cell/selection_cell_bloc.dart

@@ -16,7 +16,7 @@ class SelectionCellBloc extends Bloc<SelectionCellEvent, SelectionCellState> {
   final SingleFieldListener _fieldListener;
 
   SelectionCellBloc({
-    required GridCellIdentifier cellData,
+    required GridCell cellData,
   })  : _service = SelectOptionService(),
         _cellListener = CellListener(rowId: cellData.rowId, fieldId: cellData.field.id),
         _fieldListener = SingleFieldListener(fieldId: cellData.field.id),
@@ -93,12 +93,12 @@ class SelectionCellEvent with _$SelectionCellEvent {
 @freezed
 class SelectionCellState with _$SelectionCellState {
   const factory SelectionCellState({
-    required GridCellIdentifier cellData,
+    required GridCell cellData,
     required List<SelectOption> options,
     required List<SelectOption> selectedOptions,
   }) = _SelectionCellState;
 
-  factory SelectionCellState.initial(GridCellIdentifier cellData) => SelectionCellState(
+  factory SelectionCellState.initial(GridCell cellData) => SelectionCellState(
         cellData: cellData,
         options: [],
         selectedOptions: [],

+ 2 - 2
frontend/app_flowy/lib/workspace/application/grid/cell/selection_editor_bloc.dart

@@ -18,7 +18,7 @@ class SelectOptionEditorBloc extends Bloc<SelectOptionEditorEvent, SelectOptionE
   Timer? _delayOperation;
 
   SelectOptionEditorBloc({
-    required GridCellIdentifier cellData,
+    required GridCell cellData,
     required List<SelectOption> options,
     required List<SelectOption> selectedOptions,
   })  : _selectOptionService = SelectOptionService(),
@@ -174,7 +174,7 @@ class SelectOptionEditorState with _$SelectOptionEditorState {
   }) = _SelectOptionEditorState;
 
   factory SelectOptionEditorState.initial(
-    GridCellIdentifier cellData,
+    GridCell cellData,
     List<SelectOption> options,
     List<SelectOption> selectedOptions,
   ) {

+ 4 - 4
frontend/app_flowy/lib/workspace/application/grid/cell/text_cell_bloc.dart

@@ -11,7 +11,7 @@ class TextCellBloc extends Bloc<TextCellEvent, TextCellState> {
 
   TextCellBloc({
     required this.service,
-    required GridCellIdentifier cellData,
+    required GridCell cellData,
   }) : super(TextCellState.initial(cellData)) {
     on<TextCellEvent>(
       (event, emit) async {
@@ -53,7 +53,7 @@ class TextCellBloc extends Bloc<TextCellEvent, TextCellState> {
 @freezed
 class TextCellEvent with _$TextCellEvent {
   const factory TextCellEvent.initial() = _InitialCell;
-  const factory TextCellEvent.didReceiveCellData(GridCellIdentifier cellData) = _DidReceiveCellData;
+  const factory TextCellEvent.didReceiveCellData(GridCell cellData) = _DidReceiveCellData;
   const factory TextCellEvent.updateText(String text) = _UpdateText;
 }
 
@@ -61,10 +61,10 @@ class TextCellEvent with _$TextCellEvent {
 class TextCellState with _$TextCellState {
   const factory TextCellState({
     required String content,
-    required GridCellIdentifier cellData,
+    required GridCell cellData,
   }) = _TextCellState;
 
-  factory TextCellState.initial(GridCellIdentifier cellData) => TextCellState(
+  factory TextCellState.initial(GridCell cellData) => TextCellState(
         content: cellData.cell?.content ?? "",
         cellData: cellData,
       );

+ 7 - 3
frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart

@@ -13,13 +13,17 @@ part 'grid_bloc.freezed.dart';
 class GridBloc extends Bloc<GridEvent, GridState> {
   final GridService _gridService;
   final GridFieldCache fieldCache;
-  final GridRowCache rowCache;
+  late final GridRowCache rowCache;
 
   GridBloc({required View view})
       : _gridService = GridService(gridId: view.id),
         fieldCache = GridFieldCache(gridId: view.id),
-        rowCache = GridRowCache(gridId: view.id),
         super(GridState.initial(view.id)) {
+    rowCache = GridRowCache(
+      gridId: view.id,
+      dataDelegate: GridRowDataDelegateAdaptor(fieldCache),
+    );
+
     on<GridEvent>(
       (event, emit) async {
         await event.map(
@@ -77,7 +81,7 @@ class GridBloc extends Bloc<GridEvent, GridState> {
       () => result.fold(
         (fields) {
           fieldCache.fields = fields.items;
-          rowCache.updateWithBlock(grid.blockOrders, fieldCache.unmodifiableFields);
+          rowCache.updateWithBlock(grid.blockOrders);
 
           emit(state.copyWith(
             grid: Some(grid),

+ 43 - 0
frontend/app_flowy/lib/workspace/application/grid/grid_service.dart

@@ -8,6 +8,8 @@ import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
 import 'package:flutter/foundation.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 
+import 'row/row_service.dart';
+
 class GridService {
   final String gridId;
   GridService({
@@ -152,3 +154,44 @@ class GridFieldCache {
     _fieldNotifier.fields = fields;
   }
 }
+
+class GridRowDataDelegateAdaptor extends GridRowDataDelegate {
+  final GridFieldCache _cache;
+
+  GridRowDataDelegateAdaptor(GridFieldCache cache) : _cache = cache;
+  @override
+  UnmodifiableListView<Field> get fields => _cache.unmodifiableFields;
+
+  @override
+  GridRow buildGridRow(RowOrder rowOrder) {
+    return GridRow(
+      gridId: _cache.gridId,
+      fields: _cache.unmodifiableFields,
+      rowId: rowOrder.rowId,
+      height: rowOrder.height.toDouble(),
+    );
+  }
+
+  @override
+  void onFieldChanged(FieldDidUpdateCallback callback) {
+    _cache.addListener(listener: () {
+      callback();
+    });
+  }
+
+  @override
+  CellDataMap buildCellDataMap(Row rowData) {
+    var map = CellDataMap.new();
+    for (final field in fields) {
+      if (field.visibility) {
+        map[field.id] = GridCell(
+          rowId: rowData.id,
+          gridId: _cache.gridId,
+          cell: rowData.cellByFieldId[field.id],
+          field: field,
+        );
+      }
+    }
+    return map;
+  }
+}

+ 11 - 67
frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart

@@ -1,7 +1,4 @@
 import 'dart:collection';
-
-import 'package:app_flowy/workspace/application/grid/grid_service.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'dart:async';
@@ -10,21 +7,15 @@ import 'package:dartz/dartz.dart';
 
 part 'row_bloc.freezed.dart';
 
-typedef CellDataMap = LinkedHashMap<String, GridCellIdentifier>;
-
 class RowBloc extends Bloc<RowEvent, RowState> {
   final RowService _rowService;
-  final GridFieldCache _fieldCache;
   final GridRowCache _rowCache;
-  void Function()? _rowListenCallback;
-  void Function()? _fieldListenCallback;
+  void Function()? _rowListenFn;
 
   RowBloc({
     required GridRow rowData,
-    required GridFieldCache fieldCache,
     required GridRowCache rowCache,
   })  : _rowService = RowService(gridId: rowData.gridId, rowId: rowData.rowId),
-        _fieldCache = fieldCache,
         _rowCache = rowCache,
         super(RowState.initial(rowData)) {
     on<RowEvent>(
@@ -37,92 +28,45 @@ class RowBloc extends Bloc<RowEvent, RowState> {
           createRow: (_CreateRow value) {
             _rowService.createRow();
           },
-          didUpdateRow: (_DidUpdateRow value) async {
-            _handleRowUpdate(value.row, emit);
-          },
-          fieldsDidUpdate: (_FieldsDidUpdate value) async {
-            await _handleFieldUpdate(emit);
-          },
-          didLoadRow: (_DidLoadRow value) {
-            _handleRowUpdate(value.row, emit);
+          didReceiveCellDatas: (_DidReceiveCellDatas value) async {
+            emit(state.copyWith(cellDataMap: Some(value.cellData)));
           },
         );
       },
     );
   }
 
-  void _handleRowUpdate(Row row, Emitter<RowState> emit) {
-    final CellDataMap cellDataMap = _makeCellDatas(row, state.rowData.fields);
-    emit(state.copyWith(cellDataMap: Some(cellDataMap)));
-  }
-
-  Future<void> _handleFieldUpdate(Emitter<RowState> emit) async {
-    final data = state.rowData.data;
-    if (data == null) {
-      return;
-    }
-
-    final CellDataMap cellDataMap = _makeCellDatas(data, state.rowData.fields);
-    emit(state.copyWith(cellDataMap: Some(cellDataMap)));
-  }
-
   @override
   Future<void> close() async {
-    if (_rowListenCallback != null) {
-      _rowCache.removeRowListener(_rowListenCallback!);
-    }
-
-    if (_fieldListenCallback != null) {
-      _fieldCache.removeListener(_fieldListenCallback!);
+    if (_rowListenFn != null) {
+      _rowCache.removeRowListener(_rowListenFn!);
     }
     return super.close();
   }
 
   Future<void> _startListening() async {
-    _fieldListenCallback = _fieldCache.addListener(
-      listener: () => add(const RowEvent.fieldsDidUpdate()),
-      listenWhen: () => !isClosed,
-    );
-
-    _rowListenCallback = _rowCache.addRowListener(
+    _rowListenFn = _rowCache.addRowListener(
       rowId: state.rowData.rowId,
-      onUpdated: (row) => add(RowEvent.didUpdateRow(row)),
+      onUpdated: (cellDatas) => add(RowEvent.didReceiveCellDatas(cellDatas)),
       listenWhen: () => !isClosed,
     );
   }
 
   Future<void> _loadRow(Emitter<RowState> emit) async {
-    final data = _rowCache.loadRow(state.rowData.rowId);
-    data.foldRight(null, (data, _) {
+    final data = _rowCache.loadCellData(state.rowData.rowId);
+    data.foldRight(null, (cellDatas, _) {
       if (!isClosed) {
-        add(RowEvent.didLoadRow(data));
+        add(RowEvent.didReceiveCellDatas(cellDatas));
       }
     });
   }
-
-  CellDataMap _makeCellDatas(Row row, List<Field> fields) {
-    var map = CellDataMap.new();
-    for (final field in fields) {
-      if (field.visibility) {
-        map[field.id] = GridCellIdentifier(
-          rowId: row.id,
-          gridId: _rowService.gridId,
-          cell: row.cellByFieldId[field.id],
-          field: field,
-        );
-      }
-    }
-    return map;
-  }
 }
 
 @freezed
 class RowEvent with _$RowEvent {
   const factory RowEvent.initial() = _InitialRow;
   const factory RowEvent.createRow() = _CreateRow;
-  const factory RowEvent.fieldsDidUpdate() = _FieldsDidUpdate;
-  const factory RowEvent.didLoadRow(Row row) = _DidLoadRow;
-  const factory RowEvent.didUpdateRow(Row row) = _DidUpdateRow;
+  const factory RowEvent.didReceiveCellDatas(CellDataMap cellData) = _DidReceiveCellDatas;
 }
 
 @freezed

+ 80 - 55
frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart

@@ -8,31 +8,36 @@ import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart';
 import 'package:flutter/foundation.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
-
 import 'package:app_flowy/workspace/application/grid/grid_listener.dart';
-
 part 'row_service.freezed.dart';
 
+typedef RowUpdateCallback = void Function();
+typedef FieldDidUpdateCallback = void Function();
+typedef CellDataMap = LinkedHashMap<String, GridCell>;
+
+abstract class GridRowDataDelegate {
+  UnmodifiableListView<Field> get fields;
+  GridRow buildGridRow(RowOrder rowOrder);
+  CellDataMap buildCellDataMap(Row rowData);
+  void onFieldChanged(FieldDidUpdateCallback callback);
+}
+
 class GridRowCache {
   final String gridId;
+  final RowsNotifier _rowNotifier;
   final GridRowListener _rowsListener;
-  late final _RowsNotifier _rowNotifier;
-  UnmodifiableListView<Field> _fields = UnmodifiableListView([]);
+  final GridRowDataDelegate _dataDelegate;
 
   List<GridRow> get clonedRows => _rowNotifier.clonedRows;
 
-  GridRowCache({required this.gridId}) : _rowsListener = GridRowListener(gridId: gridId) {
-    _rowNotifier = _RowsNotifier(
-      rowBuilder: (rowOrder) {
-        return GridRow(
-          gridId: gridId,
-          fields: _fields,
-          rowId: rowOrder.rowId,
-          height: rowOrder.height.toDouble(),
-        );
-      },
-    );
+  GridRowCache({required this.gridId, required GridRowDataDelegate dataDelegate})
+      : _rowNotifier = RowsNotifier(rowBuilder: dataDelegate.buildGridRow),
+        _rowsListener = GridRowListener(gridId: gridId),
+        _dataDelegate = dataDelegate {
+    //
+    dataDelegate.onFieldChanged(() => _rowNotifier.fieldDidChange());
 
+    // listen on the row update
     _rowsListener.rowsUpdateNotifier.addPublishListener((result) {
       result.fold(
         (changesets) {
@@ -68,9 +73,9 @@ class GridRowCache {
     });
   }
 
-  VoidCallback addRowListener({
+  RowUpdateCallback addRowListener({
     required String rowId,
-    void Function(Row)? onUpdated,
+    void Function(CellDataMap)? onUpdated,
     bool Function()? listenWhen,
   }) {
     listenrHandler() {
@@ -82,12 +87,22 @@ class GridRowCache {
         return;
       }
 
-      _rowNotifier._changeReason.whenOrNull(update: (indexs) {
+      notify() {
         final row = _rowNotifier.rowDataWithId(rowId);
-        if (indexs[rowId] != null && row != null) {
-          onUpdated(row);
+        if (row != null) {
+          final cellDataMap = _dataDelegate.buildCellDataMap(row);
+          onUpdated(cellDataMap);
         }
-      });
+      }
+
+      _rowNotifier._changeReason.whenOrNull(
+        update: (indexs) {
+          if (indexs[rowId] != null) {
+            notify();
+          }
+        },
+        fieldDidChange: () => notify(),
+      );
     }
 
     _rowNotifier.addListener(listenrHandler);
@@ -98,10 +113,10 @@ class GridRowCache {
     _rowNotifier.removeListener(callback);
   }
 
-  Option<Row> loadRow(String rowId) {
+  Option<CellDataMap> loadCellData(String rowId) {
     final Row? data = _rowNotifier.rowDataWithId(rowId);
     if (data != null) {
-      return Some(data);
+      return Some(_dataDelegate.buildCellDataMap(data));
     }
 
     final payload = RowIdentifierPayload.create()
@@ -117,8 +132,7 @@ class GridRowCache {
     return none();
   }
 
-  void updateWithBlock(List<GridBlockOrder> blocks, UnmodifiableListView<Field> fields) {
-    _fields = fields;
+  void updateWithBlock(List<GridBlockOrder> blocks) {
     final rowOrders = blocks.expand((block) => block.rowOrders).toList();
     _rowNotifier.reset(rowOrders);
   }
@@ -136,13 +150,13 @@ class GridRowCache {
   }
 }
 
-class _RowsNotifier extends ChangeNotifier {
+class RowsNotifier extends ChangeNotifier {
   List<GridRow> _rows = [];
   HashMap<String, Row> _rowDataMap = HashMap();
   GridRowChangeReason _changeReason = const InitialListState();
   final GridRow Function(RowOrder) rowBuilder;
 
-  _RowsNotifier({
+  RowsNotifier({
     required this.rowBuilder,
   });
 
@@ -199,9 +213,10 @@ class _RowsNotifier extends ChangeNotifier {
       final index = newRows.indexWhere((row) => row.rowId == rowOrder.rowId);
       if (index != -1) {
         newRows.removeAt(index);
-        // Remove the cache data
+        // Remove the old row data, the data will be filled if the loadRow method gets called.
         _rowDataMap.remove(rowOrder.rowId);
         newRows.insert(index, rowBuilder(rowOrder));
+
         updatedIndexs[rowOrder.rowId] = UpdatedIndex(index: index, rowId: rowOrder.rowId);
       }
     }
@@ -209,14 +224,19 @@ class _RowsNotifier extends ChangeNotifier {
     _update(newRows, GridRowChangeReason.update(updatedIndexs));
   }
 
-  void _update(List<GridRow> rows, GridRowChangeReason changeReason) {
+  void fieldDidChange() {
+    _update(_rows, const GridRowChangeReason.fieldDidChange());
+  }
+
+  void _update(List<GridRow> rows, GridRowChangeReason reason) {
     _rows = rows;
-    _changeReason = changeReason;
+    _changeReason = reason;
 
-    changeReason.map(
+    _changeReason.map(
       insert: (_) => notifyListeners(),
       delete: (_) => notifyListeners(),
       update: (_) => notifyListeners(),
+      fieldDidChange: (_) => notifyListeners(),
       initial: (_) {},
     );
   }
@@ -227,13 +247,17 @@ class _RowsNotifier extends ChangeNotifier {
     _rowDataMap[rowData.id] = rowData;
     final index = _rows.indexWhere((row) => row.rowId == rowData.id);
     if (index != -1) {
+      // update the corresponding row in _rows if they are not the same
       if (_rows[index].data != rowData) {
         final row = _rows.removeAt(index).copyWith(data: rowData);
         _rows.insert(index, row);
 
+        // Calculate the update index
         final UpdatedIndexs updatedIndexs = UpdatedIndexs();
         updatedIndexs[row.rowId] = UpdatedIndex(index: index, rowId: row.rowId);
         _changeReason = GridRowChangeReason.update(updatedIndexs);
+
+        //
         notifyListeners();
       }
     }
@@ -296,16 +320,6 @@ class RowService {
   }
 }
 
-@freezed
-class GridCellIdentifier with _$GridCellIdentifier {
-  const factory GridCellIdentifier({
-    required String gridId,
-    required String rowId,
-    required Field field,
-    Cell? cell,
-  }) = _GridCellIdentifier;
-}
-
 @freezed
 class GridRow with _$GridRow {
   const factory GridRow({
@@ -317,13 +331,32 @@ class GridRow with _$GridRow {
   }) = _GridRow;
 }
 
+@freezed
+class GridCell with _$GridCell {
+  const factory GridCell({
+    required String gridId,
+    required String rowId,
+    required Field field,
+    Cell? cell,
+  }) = _GridCell;
+}
+
 typedef InsertedIndexs = List<InsertedIndex>;
 typedef DeletedIndexs = List<DeletedIndex>;
 typedef UpdatedIndexs = LinkedHashMap<String, UpdatedIndex>;
 
+@freezed
+class GridRowChangeReason with _$GridRowChangeReason {
+  const factory GridRowChangeReason.insert(InsertedIndexs items) = _Insert;
+  const factory GridRowChangeReason.delete(DeletedIndexs items) = _Delete;
+  const factory GridRowChangeReason.update(UpdatedIndexs indexs) = _Update;
+  const factory GridRowChangeReason.fieldDidChange() = _FieldDidChange;
+  const factory GridRowChangeReason.initial() = InitialListState;
+}
+
 class InsertedIndex {
-  int index;
-  String rowId;
+  final int index;
+  final String rowId;
   InsertedIndex({
     required this.index,
     required this.rowId,
@@ -331,8 +364,8 @@ class InsertedIndex {
 }
 
 class DeletedIndex {
-  int index;
-  GridRow row;
+  final int index;
+  final GridRow row;
   DeletedIndex({
     required this.index,
     required this.row,
@@ -340,18 +373,10 @@ class DeletedIndex {
 }
 
 class UpdatedIndex {
-  int index;
-  String rowId;
+  final int index;
+  final String rowId;
   UpdatedIndex({
     required this.index,
     required this.rowId,
   });
 }
-
-@freezed
-class GridRowChangeReason with _$GridRowChangeReason {
-  const factory GridRowChangeReason.insert(InsertedIndexs items) = _Insert;
-  const factory GridRowChangeReason.delete(DeletedIndexs items) = _Delete;
-  const factory GridRowChangeReason.update(UpdatedIndexs indexs) = _Update;
-  const factory GridRowChangeReason.initial() = InitialListState;
-}

+ 1 - 5
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart

@@ -227,16 +227,12 @@ class _GridRowsState extends State<_GridRows> {
     GridRow rowData,
     Animation<double> animation,
   ) {
-    final bloc = context.read<GridBloc>();
-    final fieldCache = bloc.fieldCache;
-    final rowCache = bloc.rowCache;
-
+    final rowCache = context.read<GridBloc>().rowCache;
     return SizeTransition(
       sizeFactor: animation,
       child: GridRowWidget(
         blocBuilder: () => RowBloc(
           rowData: rowData,
-          fieldCache: fieldCache,
           rowCache: rowCache,
         ),
         key: ValueKey(rowData.rowId),

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart

@@ -7,7 +7,7 @@ import 'number_cell.dart';
 import 'selection_cell/selection_cell.dart';
 import 'text_cell.dart';
 
-Widget buildGridCell(GridCellIdentifier cellData) {
+Widget buildGridCell(GridCell cellData) {
   final key = ValueKey(cellData.field.id + cellData.rowId);
   switch (cellData.field.fieldType) {
     case FieldType.Checkbox:

+ 2 - 2
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_container.dart

@@ -55,8 +55,8 @@ class CellContainer extends StatelessWidget {
   }
 }
 
-abstract class GridCell extends StatefulWidget {
-  const GridCell({Key? key}) : super(key: key);
+abstract class GridCellWidget extends StatefulWidget {
+  const GridCellWidget({Key? key}) : super(key: key);
 
   void setFocus(BuildContext context, bool value) {
     Provider.of<CellStateNotifier>(context, listen: false).isFocus = value;

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart

@@ -6,7 +6,7 @@ import 'package:flutter/widgets.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
 class CheckboxCell extends StatefulWidget {
-  final GridCellIdentifier cellData;
+  final GridCell cellData;
 
   const CheckboxCell({
     required this.cellData,

+ 2 - 2
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell.dart

@@ -8,8 +8,8 @@ import 'package:flutter/widgets.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:table_calendar/table_calendar.dart';
 
-class DateCell extends GridCell {
-  final GridCellIdentifier cellData;
+class DateCell extends GridCellWidget {
+  final GridCell cellData;
 
   const DateCell({
     required this.cellData,

+ 2 - 2
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart

@@ -6,8 +6,8 @@ import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/c
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
-class NumberCell extends GridCell {
-  final GridCellIdentifier cellData;
+class NumberCell extends GridCellWidget {
+  final GridCell cellData;
 
   const NumberCell({
     required this.cellData,

+ 4 - 4
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_cell.dart

@@ -7,8 +7,8 @@ import 'package:flutter_bloc/flutter_bloc.dart';
 import 'extension.dart';
 import 'selection_editor.dart';
 
-class SingleSelectCell extends GridCell {
-  final GridCellIdentifier cellData;
+class SingleSelectCell extends GridCellWidget {
+  final GridCell cellData;
 
   const SingleSelectCell({
     required this.cellData,
@@ -63,8 +63,8 @@ class _SingleSelectCellState extends State<SingleSelectCell> {
 }
 
 //----------------------------------------------------------------
-class MultiSelectCell extends GridCell {
-  final GridCellIdentifier cellData;
+class MultiSelectCell extends GridCellWidget {
+  final GridCell cellData;
 
   const MultiSelectCell({
     required this.cellData,

+ 2 - 2
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart

@@ -25,7 +25,7 @@ import 'text_field.dart';
 const double _editorPannelWidth = 300;
 
 class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate {
-  final GridCellIdentifier cellData;
+  final GridCell cellData;
   final List<SelectOption> options;
   final List<SelectOption> selectedOptions;
   final VoidCallback onDismissed;
@@ -66,7 +66,7 @@ class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate {
 
   static void show(
     BuildContext context,
-    GridCellIdentifier cellData,
+    GridCell cellData,
     List<SelectOption> options,
     List<SelectOption> selectedOptions,
     VoidCallback onDismissed,

+ 2 - 2
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart

@@ -5,8 +5,8 @@ import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'cell_container.dart';
 
-class GridTextCell extends GridCell {
-  final GridCellIdentifier cellData;
+class GridTextCell extends GridCellWidget {
+  final GridCell cellData;
   const GridTextCell({
     required this.cellData,
     Key? key,

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/cell/number_cell.dart

@@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
 class NumberCell extends StatefulWidget {
-  final GridCellIdentifier cellData;
+  final GridCell cellData;
 
   const NumberCell({
     required this.cellData,

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/number_cell.dart

@@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
 class NumberCell extends StatefulWidget {
-  final GridCellIdentifier cellData;
+  final GridCell cellData;
 
   const NumberCell({
     required this.cellData,