패키지, 저장소 및 앱 카테고리 검색

패키지 상세v5.0.0

diffutil_dart

두 목록 간의 차이를 편집 작업 목록으로 계산합니다. 예를 들어, StatefulWidget을 유지할 필요 없이 Flutter 목록을 암시적으로 애니메이션화하는 데 사용됩니다.

AndroidiOSWebmacOSWindowsLinux
30일 다운로드
21.9만
좋아요
104
Pub 점수
160

패키지 설치

flutter pub add diffutil_dart

패키지 개요

공개 정보를 바탕으로 생성한 선택 가이드입니다.

diffutil_dart는 두 목록 간의 차이를 계산하고 하나의 목록을 다른 목록으로 변환하기 위한 편집 작업(삽입, 삭제, 이동) 시퀀스를 생성합니다. 이를 통해 StatefulWidget 위젯에서 상태를 수동으로 관리하지 않고도 Flutter 리스트에서 효율적이고 암시적인 애니메이션을 가능하게 합니다. 특히 동적 데이터를 다룰 때 최소한의 재구성으로 UI를 업데이트하여 성능과 반응성을 향상시키는 데 특히 유용합니다. 이 패키지는 가볍고 Flutter가 지원하는 모든 주요 플랫폼과 호환됩니다.

사용 사례

  • Flutter에서 목록 업데이트 애니메이션화
  • 목록 변경 사항을 효율적으로 동기화합니다
  • 불필요한 위젯 재구성 줄이기
  • 스무스 스크롤 전환 구현
  • 동적 데이터 소스 업데이트
  • 리스트의 상태 관리를 단순화하기

주요 기능

  • 정밀한 편집 작업을 생성합니다
  • 삽입, 삭제 및 이동 작업을 지원합니다
  • 더 나은 성능을 위한 최소 재빌드
  • 크로스 플랫폼 호환성
  • 경량이며 통합이 쉬움
  • 수동 상태 관리 필요 없음

적합한 대상

  • 동적 목록을 사용하는 Flutter 개발자
  • 부드러운 UI 애니메이션을 우선시하는 팀
  • 자주 목록이 업데이트되는 앱
  • 리스트 처리에서 반복 코드를 줄이고자 하는 사람
  • 고성능 리스트 렌더링을 목표로 하는 프로젝트

고려 사항

  • 편집 작업 로직에 대한 이해가 필요합니다
  • 간단한 목록 구조에 가장 적합
  • 복잡한 중첩된 데이터를 최적화하지 않을 수 있습니다
  • 리스트가 아닌 데이터 유형에는 적합하지 않음
  • 리스트 간 차이 비교에 제한됨
  • 기본적으로 깊은 동등성을 처리하지 않습니다

원본 README

연결된 소스 저장소의 README 원문 스냅샷입니다. 최신 내용은 저장소에서 확인하세요.

diffutil.dart

Pub Package Build Status codecov

Calculate the difference between two lists.

Heavily inspired bei Android's DiffUtil class, the code was adopted for Dart.

Uses Myers algorithm internally. For an explanation of how the algorithm works internally, for details I recommend this great series of articles: https://blog.jcoglan.com/2017/02/12/the-myers-diff-algorithm-part-1/

What is this good for?

There are often situations, where an app displays a list of items, which are fetched from an external data source like a server endpoint or a database, and updates are not sent as delta, but as a whole new list.

It can be useful to take the old list and the new list and calculate the difference between those two, for example when animating the insertion and removal of new items in the displayed list (See diffutil_sliverlist).

This package does exactly that: It takes two lists and calculates the difference (or to be more accurate: edit script) between those two lists as list of Insert, Remove, Change (only when using custom delegates) and Move (when enabled) operations.

Usage

Calculating diffs:

Simple usage:

final diffResult = calculateListDiff<int>([1, 2 ,3], [1, 3, 4]);

Custom equality:

final diffResult = calculateListDiff<YourClassWithId>(oldList, newList, (o1, o2) => o1.id == o2.id);

If you don't want to use plain old Dart lists (for example if you're using built_value or kt.dart), and don't want to convert your custom list to standard lists, you can use the calculateDiff function and implement your own DiffDelegate easily.

Or use calculateCustomListDiff and CustomListDiffDelegate.

Move detection is disabled by default.

Using the result:

Call .getUpdates() on the diffResult to get a List of DiffUpdate objects. These are sealed classes of type Insert, Remove, Change or Move. Move operations are only calculated if calculateListDiff was called with detectMoves: true

The order of these operations matters! They describe how to turn the previous list into the new list, when applied in the order as they are returned.

  for (final update in diffResult.getUpdates())
    update.when(
      insert: (pos, count) => print("inserted $count on $pos"),
      remove: (pos, count) => print("removed $count on $pos"),
      change: (pos, payload) => print("changed on $pos with payload $payload"),
      move: (from, to) => print("move $from to $to"),
    );

By default, Insert and Remove Operations are batched. (e.g. multiple consecutive inserts or removes are represented by a single Insert/Remove object with a count field > 1). If you want to turn off edit script batching, call getUpdates(batch: false). This means, every Insert and Remove operation will have a count of 1 and the edit script of [] and [1, 2] will be

[Insert(position: 0, count : 1), Insert(position: 0, count :1 )]

instead of

[Insert(position: 0, count: 2)]

Updates with data

If you need the concrete items that have been inserted/removed/changed/moved, call getUpdatesWithData().


     diffutil.calculateListDiff([1, 2, 3], [1, 0, 3]).getUpdatesWithData();

returns

      [
        DataRemove(position: 1, data: 2),
        DataInsert(position: 1, data: 0)
      ];

The result of getUpdatesWithData() cannot be batched. You can use the resulting Iterable<DataDiffUpdate> like this:

 for (final update in updates) {
      update.when(
        insert: (pos, data) => print('insert $pos $data'),
        remove: (pos, data) => print('remove $pos $data'),
        change: (pos, oldData, newData) => print('change on $pos from $oldData to $newData'),
        move: (from, to, data) => print('move $data from $from to $to'),
      );
    }

Note that if you implement you own DiffDelegate and call calculateDiff() directly, the DiffDelegate also needs to implement IndexableItemDiffDelegate if you want to call getUpdatesWithData().

Change Operations

For data objects that have some meaningful identity (like an unique id field), you can enable the calculation of Change operations. For this, you need to implement your own DiffDelegate and override the areItemsTheSame method.

Let's say we have a class called DataObject which is defined like this:


class DataObject {
  final int id;
  final int? payload;

  DataObject({required this.id, this.payload});
}

The delegate can be implemented like this:

class DataObjectListDiff extends diffutil.ListDiffDelegate<DataObject> {
  DataObjectListDiff(List<DataObject> oldList, List<DataObject> newList)
      : super(oldList, newList);

  @override
  bool areContentsTheSame(int oldItemPosition, int newItemPosition) {
    return equalityChecker(oldList[oldItemPosition], newList[newItemPosition]);
  }

  @override
  bool areItemsTheSame(int oldItemPosition, int newItemPosition) {
    return oldList[oldItemPosition].id == newList[newItemPosition].id;
  }
}

With this, Change Operations are emitted if the id of an object stays the same between oldList and newList, but it's data changes.

Performance metrics:

Same as Android's DiffUtil:

  • O(N) space
  • O(N + D^2) time performance where D is the length of the edit script.
  • additional O(N^2) time where N is the total number of added and removed items if move detection is enabled

The edit script is the smallest set of operations needed to transform the first list into the second list.

카테고리

소스 저장소

이 패키지를 사용하는 프로젝트