dispatchNewList method

Future<void> dispatchNewList(
  1. T newList, {
  2. bool detectMoves = false,
})

It replaces the current list with the new one. Differences are calculated and then dispatched to the controller.

Implementation

Future<void> dispatchNewList(T newList, {bool detectMoves = false}) async {
  _processingList = newList;

  _DiffResultDispatcher dr;
  var futureOr = _computeDiffs(_currentList, newList, detectMoves);
  if (futureOr is Future<_DiffResultDispatcher?>) {
    dr = await futureOr;
  } else {
    dr = futureOr;
  }

  if (newList != _processingList || _processingList == null) {
    return; // discard result
  }

  _oldList = _currentList;
  _currentList = _processingList!;
  _processingList = null;

  final oldList = _oldList!;

  final cl = _ChangeList(comparator.lengthOf(oldList));

  Widget callOldListBuilder(List<_MovedRange> l, int index,
      BuildContext context, AnimatedWidgetBuilderData data) {
    int? oldIndex;
    var i = index;
    for (final e in l) {
      if (i < e.length) {
        oldIndex = e.from + i;
        break;
      }
      i -= e.length;
    }
    assert(oldIndex != null);
    return builder.call(context, oldList, oldIndex!, data);
  }

  controller.batch(() {
    dr._dispatchUpdatesTo(
      onInsert: (position, count) {
        controller.notifyInsertedRange(position, count);
        cl.replaceOrChange(position, 0, count);
      },
      onChange: (position, count) {
        final l = cl.apply(position, count)!;
        assert(l.isNotEmpty);
        controller.notifyChangedRange(position, count,
            (context, index, data) {
          return callOldListBuilder(l, index, context, data);
        });
        cl.replaceOrChange(position, count, count);
      },
      onRemove: (position, count) {
        final l = cl.apply(position, count)!;
        assert(l.isNotEmpty);
        controller.notifyRemovedRange(position, count,
            (context, index, data) {
          return callOldListBuilder(l, index, context, data);
        });
        cl.replaceOrChange(position, count, 0);
      },
      onReplace: (position, removeCount, insertCount) {
        final l = cl.apply(position, removeCount)!;
        assert(l.isNotEmpty);
        controller.notifyReplacedRange(position, removeCount, insertCount,
            (context, index, data) {
          return callOldListBuilder(l, index, context, data);
        });
        cl.replaceOrChange(position, removeCount, insertCount);
      },
      onMove: (position, toPosition, count) {
        controller.notifyMovedRange(position, count, toPosition);
        cl.move(position, count, toPosition);
      },
    );
  });
}