Skip to content

msglist: Fix the double-fetch glitch #2104

@sm-sayedi

Description

@sm-sayedi

Prompted by #1989 (comment).

In a message list, when we want to load more message history by fling scrolling to the top, a request is made to fetch more messages once a specific point is reached. When new messages arrive and the fling is still going on, another request for the next batch will be made. This will not happen if we're scrolling normally or if there is no scrolling at the time of messages arriving.

Here's the code snippet for the method that fetches more messages:

void _handleScrollMetrics(ScrollMetrics scrollMetrics) {
  // ...
  if (scrollMetrics.extentBefore < kFetchMessagesBufferPixels) {
    model.fetchOlder();
  }
  if (scrollMetrics.extentAfter < kFetchMessagesBufferPixels) {
    model.fetchNewer();
  }
}

The cause for this glitch is that this method gets called again with ScrollMetrics still not yet updated to account for the newly-added messages. This relates to how SchedulerBinding executes different tasks when producing a new frame, like first executing transient callbacks (typically ticking animations) followed by persistent callbacks (typically the build/layout/paint pipeline), and so on.
So whenever a new message batch arrives, the message list view will be marked dirty for the next frame. With the ongoing fling, the underlying animation of fling registers transient callback(s) for ScrollPosition.setPixels to be executed in the transient callbacks phase at the start of the next frame. ScrollPosition.setPixels will then notify its listeners, eventually calling _scrollChanged and in turn the current method with old ScrollMetrics, causing the second batch fetch. Then in the persistent callbacks phase, ScrollMetrics will be updated to account for the newly-added messages, effective from that point onward.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

Status

No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions