Skip to content

fix(list-view): handle reusing wrong view - #9023

Merged
NathanWalker merged 1 commit into
NativeScript:masterfrom
edusperoni:lview-fix
Nov 12, 2020
Merged

NathanWalker merged 1 commit into
NativeScript:masterfrom
edusperoni:lview-fix

Conversation

@edusperoni

@edusperoni edusperoni commented Nov 11, 2020 •

Copy link
Copy Markdown
Contributor

PR Checklist

What is the current behavior?

public getView(index: number, convertView: android.view.View, parent: android.view.ViewGroup): android.view.View never checks if convertView is of the right type for the template. This usually isn't an issue because android calls getItemViewType(index: number) to check if the view is of the correct type (template). If for some reason the items have changed mid-execution, though, getItemViewType(index: number) will return a different template from what the view actually is.

Scenario 1

Consider this scenario (listview where only 2 items are visible):

red
green
green
green

While rendering red, items change to

green
green
green
green

You'll see the wrong representation because it should never change view types, but it did.

red // android believes this is a green view!
green

This is happening:

getItemViewType 0 red // we tell we need a red view
getView 0 null // there's no available red view, get a new view
getItemViewType 0 green // view 0 is now green, so android stores it as such
// scroll down to a green view
getItemViewType 3 green // needs a green view. Nice! we have view 0 that is green
getView 3 viewThatIsActuallyRed
// crash because red is not green

This mainly happens because we're first instantiating a template, then we pass this template to itemLoading which changes it, and then we're using the new data. Ideally these changes should never happen on itemLoading, but they sometimes do because #8904 isn't merged yet.

Scenario 2

Like scenario 1, the dataset has changed mid-render (seems to happen randomly when a few frames are lost), so ListView correctly identifies that the index is of template X but when it checks again, it's now of template Y

getItemViewType 0 red // we tell we need a red view
getView 0 null // there's no available red view, get a new view
getItemViewType 0 red// view 0 is still red
// dataset changes
getItemViewType 0 green // it's now green
// scroll down to a green view
getItemViewType 3 green // needs a green view
getView 3 viewThatIsActuallyRed // for some reason it overwrote view 0 as green instead of red
// crash because red is not green

What is the new behavior?

We always check if the correct template is being used. This may sometimes still show an inconsistent listview (like in the example above, we still show red on top even though it should be green), but it will not crash anymore.

I'm not sure of why this issue started happening still.

Fixes #6284.

@cla-bot cla-bot Bot added the cla: yes label Nov 11, 2020
@edusperoni
edusperoni marked this pull request as draft November 11, 2020 16:34
@edusperoni

Copy link
Copy Markdown
Contributor Author

I believe most of the issues will be fixed with #8904, so I converted this to a draft. That said, this can be merged in the future to always have a safeguard against these types of crashes.

@edusperoni
edusperoni marked this pull request as ready for review November 11, 2020 21:36
@edusperoni

Copy link
Copy Markdown
Contributor Author

After further investigation this issue can occur on a normally functioning app that changes the dataset quickly. I haven't managed to reproduce it in tests but I believe performance is a factor (probably a race condition), which is difficult to emulate.

The current test scenario should cover it, though.

@NathanWalker
NathanWalker merged commit 64e0aa6 into NativeScript:master Nov 12, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ListView causing app to crash

2 participants