-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Insertion order with getUpdatesWithData
#14
Comments
I understand your problem, unfortunately, I don't have a solution as of yet. You could maybe do a post-processing stuff on the |
That's exactly what I currently do, but I feel this package would be even more valuable than already is if it would handle this internally. |
Yes. I don't know how to define the "best" update order for any list diff, though. |
I feel there's no such thing as best but rather useful. |
Yes, I also don't know how to define the usefulness of the diff result. |
In my particular case I do this only when I have multiple inserts that I need to handle, for obvious reasons(order of UI inserts). I feel this works well when there are multiple consecutive inserts. This would get a bit more complex when dealing with deletes too. |
Thanks. It might be possible to get your expected insertion order by tweaking the iteration order of the algorithm, especially reversing the iteration order of these loop: However, when reversing the iteration order, the body of the loops needs to be tweaked as well. |
Another way to go would be to implement some sort of Batching (like when you call This would be easier to implement. |
That's not gonna work well because you can't obtained the right order by doing inserts at the same position, no matter where that position is. You basically need |
Something like this? import 'package:diffutil_dart/src/model/diffupdate_with_data.dart';
extension Sort<T> on Iterable<DataDiffUpdate<T>> {
Iterable<DataDiffUpdate<T>> reorder() sync* {
DataDiffUpdate<T>? lastUpdate;
final List<DataDiffUpdate<T>> _batchedUpdates = [];
for (final update in this) {
if (lastUpdate.runtimeType != update.runtimeType) {
if (_batchedUpdates.isNotEmpty) {
// end of consecutive updates of the same type
yield* _yieldResult(_batchedUpdates);
_batchedUpdates.clear();
yield update;
} else {
// first new update
_batchedUpdates.add(update);
}
lastUpdate = update;
} else {
// moves and changes cannot be batched
if (lastUpdate is DataMove<T> || lastUpdate is DataChange<T>) {
yield lastUpdate!;
lastUpdate = update;
} else if (update is DataInsert<T>) {
// handle consecutive inserts
final lastInsert = lastUpdate as DataInsert<T>;
if (update.position == lastInsert.position) {
_batchedUpdates.add(update);
} else {
yield* _yieldResult(_batchedUpdates);
_batchedUpdates.clear();
yield update;
lastUpdate = update;
}
} else {
// handle consecutive deletes
final remove = update as DataRemove<T>;
final lastRemove = lastUpdate as DataRemove<T>;
if (remove.position == lastRemove.position) {
_batchedUpdates.add(update);
} else {
yield* _yieldResult(_batchedUpdates);
_batchedUpdates.clear();
yield update;
lastUpdate = update;
}
}
}
}
// yield last items
yield* _yieldResult(_batchedUpdates);
}
Iterable<DataDiffUpdate<T>> _yieldResult(List<DataDiffUpdate<T>> updates) sync* {
if (updates.isEmpty) {
return;
}
int correction = updates.first is DataInsert<T> ? 0 : updates.length - 1;
for (final correctedUpdate in updates.reversed) {
yield correctedUpdate.when(
insert: (pos, data) => DataDiffUpdate.insert(position: pos + correction++, data: data),
remove: (pos, data) => DataDiffUpdate.remove(position: pos + correction--, data: data),
change: (_, __, ___) => throw AssertionError("unreachable"),
move: (_, __, ___) => throw AssertionError("unreachable"));
}
}
} (note: proof of concept, this is untested and may be buggy) |
Looks like a promising starting point. And yeah, writing some tests would help solidify it. |
I'm using you library with an animated list and I'm also aiming to animate the initial items rendering.
I noticed that when using
getUpdatesWithData
and comparing an initial empty list with some incoming data, e.g.:[]
with[Model1(), Model2()]
, the insertion order will be:Model2
at0
,Model1
at0
.This is obviously bad in terms of UI, since the logic way of seeing items appearing on the screen would start with first and end with the last one.
What's your take on this and have you planned on addressing this @knaeckeKami ?
The text was updated successfully, but these errors were encountered: