Clone
Mihai Chira
committed
on 03 Sep 14
FLEX-28291 CAUSE: Please see the fxp attached to the ticket for a way to reproduce this bug. From the Flex Jira bugs and the bug reports in … Show more
FLEX-28291 CAUSE: Please see the fxp attached to the ticket for a way to reproduce this bug. From the Flex Jira bugs and the bug reports in our application I'm sure there are many other ways, but that's the one I could find.

There are ways to time the call to getMajorSize() on LinearLayoutVector in such a way that at that particular moment it's not yet synchronised with the DataGroup's current dataProvider, but instead with the previous one. (This applies for a snapshot before and after it's refresh()ed, as the items can vary wildly, as in the attachment). But getMajorSize() assumes that its blockTable is an accurate mapping of the current dataProvider length (disguised as DataGroup.numElements), and that therefore the index it receives as a parameter will exist (after the 'index >> BLOCK_SHIFT' mapping) in its blockTable Vector. Indeed, its assumption is correct, because it's the responsibility of VerticalLayout and HorizontaLayout to keep it in sync with the changed dataProvider.

This possibility is opened by List.dataProviderRefreshed(), which waits for the validation cycle to finish before asking the list to ensureCaretVisibility() for an index it computed before the validation cycle. However, if the dataProvider somehow changes after the validation cycle and before UPDATE_COMPLETE, we're in trouble.

SOLUTION:

Get VerticalLayout and HorizontaLayout to call updateLLV(g) before calling getBounds() on their LinearLayoutVector. This way, at least, the blockTable Vector in LinearLayoutVector has the correct length, if incorrect (empty) data.

NOTES:

-As alluded to above, while this fix does remove the fatal, it does not actually make the list scroll to the previously selected index. To achieve that we would need to call updateDisplayListVirtual() instead of updateLLV, but that's impossible because it will fail with another fatal (Error #1009 in VerticalLayout/calculateElementWidth():1721). That's because now the DataGroup will return null for getVirtualElementAt(), as its 'virtualLayoutUnderway' is false, since the validation cycle has completed. To get around this we'd need to either call validateNow whenever the DataGroup's dataProvider is reset, refreshed or replaced, or instead remove the virtualLayoutUnderway conditional from getVirtualElementAt(), but both of these are major changes with many potential side effects. If anyone wants to investigate them, they are most welcome.

-From what I can tell, the only reason List.dataProviderRefreshed() exists is that when it redraws, the list does not keep the current scroll position, but instead starts from the top/left. If we could make it redraw directly on the current scroll position (or the maximum the new items can occupy), we would remove the need for List.dataProviderRefreshed(), thus removing the potential for this bug.

Show less

develop + 8 more