-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
fix: timeline service uninitialised across routes #19544
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
Conversation
@override | ||
TimelineService build() { | ||
final timelineUsers = ref.watch(timelineUsersIdsProvider); | ||
final service = TimelineService( | ||
assetSource: (offset, count) => _timelineRepository | ||
.getMainBucketAssets(timelineUsers, offset: offset, count: count), | ||
bucketSource: () => | ||
_timelineRepository.watchMainBucket(timelineUsers, groupBy: groupBy), | ||
); | ||
ref.onDispose(service.dispose); | ||
return service; | ||
} | ||
|
||
void localAlbum({required String albumId}) { | ||
final service = TimelineService( | ||
assetSource: (offset, count) => _timelineRepository | ||
.getLocalBucketAssets(albumId, offset: offset, count: count), | ||
bucketSource: () => | ||
_timelineRepository.watchLocalBucket(albumId, groupBy: groupBy), | ||
); | ||
ref.onDispose(service.dispose); | ||
state = service; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a particular reason these create a new service every time?
Also, the assetSource
and bucketSource
seem odd to me. Shouldn't the service be the one interacting with the repositories?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a particular reason these create a new service every time?
Yes, we use an internal buffer inside the service to preload assets when being scrolled. So when the timeline changes, we drop the older service and create a new one, essentially resetting everything.
Also, the
assetSource
andbucketSource
seem odd to me. Shouldn't the service be the one interacting with the repositories?
The service is still the one that interacts with the repositories, yes. But since each timeline requires a different number of parameters, I've handled it by abstracting the service to rely on the following two methods instead:
typedef TimelineAssetSource = Future<List<BaseAsset>> Function(
int index,
int count,
);
typedef TimelineBucketSource = Stream<List<Bucket>> Function();
Now, based on the timeline being viewed, we pass in a closure to the service that resolves the other additional arguments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps a broader discussion, but are we sure that the buffer is actually beneficial? SQLite already caches pages in-memory (relevant pragma), unlike Isar which only relies on OS-level paging. If we need to reset this buffer or store multiple buffers in memory (doing power of two allocations for the lists each time), then scan these buffers in Dart, etc., it makes me wonder if this is actually better than what SQLite is doing.
7bb5abc
to
5e9e864
Compare
5e9e864
to
704c77c
Compare
Description
Using a
ProviderScope
to override thetimelineService
for a particular sub-tree works for most cases except when we need access to the overridden service in other sub-trees like from the parent / across routes. It is addressed by making the service always initialised with the main timeline segments.Whenever a new route with a timeline is pushed, we've to now update the global service provider to use the buckets for the new route. The new route will revert the provider to the main timeline segments before being disposed