NativeScript: ListView not updating on Android
Tell us about the problem
The listview on Android behaves oddly when updating elements on particular rows, using Angular and TS, Observable
and ObservableArray
Which platform(s) does your issue occur on?
Android Only
Please provide the following version numbers that your issue occurs with:
{ “description”: “NativeScript Application”, “license”: “SEE LICENSE IN <your-license-filename>”, “readme”: “NativeScript Application”, “repository”: “<fill-your-repository-here>”, “nativescript”: { “id”: “org.nativescript.nativescriptexperimentts”, “tns-android”: { “version”: “2.3.0” }, “tns-ios”: { “version”: “2.3.0” } }, “scripts”: { “build”: “tns run android --device 1 --watch”, “livesync”: “tns livesync android --device 1 --watch” }, “dependencies”: { “@angular/common”: “2.1.2”, “@angular/compiler”: “2.1.2”, “@angular/core”: “2.1.2”, “@angular/forms”: “2.1.2”, “@angular/http”: “2.1.2”, “@angular/platform-browser”: “2.1.2”, “@angular/platform-browser-dynamic”: “2.1.2”, “@angular/router”: “3.1.2”, “nativescript-angular”: “1.1.3”, “nativescript-theme-core”: “^0.2.1”, “reflect-metadata”: “~0.1.8”, “rxjs”: “5.0.0-beta.12”, “tns-core-modules”: “2.4.0”, “typed-event-emitter”: “^1.0.3”, “typescript-collections”: “^1.2.3” }, “devDependencies”: { “babel-traverse”: “6.19.0”, “babel-types”: “6.19.0”, “babylon”: “6.14.1”, “lazy”: “1.0.11”, “nativescript-dev-android-snapshot”: “^0..”, “nativescript-dev-typescript”: “^0.3.2”, “typescript”: “^2.0.10”, “zone.js”: “~0.6.21” } }
Please tell us how to recreate the issue in as much detail as possible.
- Clone repo https://github.com/johnnyzen/NativeScript-Issue
- Run the project on Android
- Click the Add button to add a row
- You should see a counter on the row just added increment by 1
- Add another row using the Add button. Again this newly added row should also have a counter incrementing by 1.
- Now keep pressing the “Press Me” on the first row until the counter reaches 0
- When the first row counter reaches zero, the rest of the list items stop updating
Expected Behaviour
The rest of the items should continue to update as usual. THIS WORKS FINE ON IOS
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Comments: 15 (3 by maintainers)
Hi all,
I’ve investigated this issue with the project from here and the problem is visible with the latest version (if you remove GridLayout that wraps the ListView control). However the problem comes from the fact that native Android ListView control gives a visual items in an unpredictable order (when placed in a container with an unspecified height like StackLayout). I’ll try to explain:
With the first tap on a button
Add
, one DataModel is added to the collection. The interesting part is what happens on the background. Since ListView.items collection is changed ListView should update its UI - therefore creates a new item (counter.component) for added DataModel instance. This view is new and its angular representation has not been checked andngOnInit
method is called after first check. Here code subscribes for its DataModel changes and update counter. So far so good. With the second tap, another DataModel is added to collection. Here ListView again is trying to update UI, so it is trying to create views for both items. Unfortunately due to (a little bit weird logic (imo)) inside native Android ListView recycling logic it creates a new view for DataModel at 0 (first) inside data.collection and this view is clean and angular calls ngOnInit for it again, so code again subscribes for changes ofdata.collection[0]
. Most interesting part is that when creating view fordata.collection[1]
item Android ListView returns the view that was previously used for data.collection[0], but this view has been checked for changes and itsngOnInit
is not called.The solution is very simple just to be strict on MVVM pattern. As it turns out
ngOnInit
is part of the view part. I’ve made a fix for the problem - making subscription when input property model is changed. A sample code is worth a thousand words: