I am building a NativeScript Angular app with the nativescript-pedometer plugin. I set up an Observable to report new steps. When new steps are reported, I log the number to the console, update a property on the Home component and call ApplicationRef.tick()
.
The number in the UI does change, but only after a delay of at least five seconds and sometimes as long as a minute, between the time I see it in the console and the time I see it in the UI.
Instead of ApplicationRef.tick()
I also tried NgZone.run(callback)
and ChangeDetectorRef.detectChanges()
. There's a delay with any of them. If I don't include any of them, the UI never updates.
I should mention I've only tested this on iOS devices and don't know for sure whether the issue would happen on Android.
Here's home.component.ts:
import { Component, OnInit, ApplicationRef } from "@angular/core";
import { Pedometer } from "nativescript-pedometer";
import { Observable } from "rxjs";
import { take } from "rxjs/operators";
@Component({
selector: "Home",
moduleId: module.id,
templateUrl: "./home.component.html"
})
export class HomeComponent implements OnInit {
numSteps: number;
pedometer: Pedometer;
constructor(private applicationRef: ApplicationRef) {}
ngOnInit(): void {
this.numSteps = 0;
this.pedometer = new Pedometer();
this.startUpdates().subscribe(response => {
console.log('New step count received from pedometer:');
console.log(response.steps);
this.numSteps = response.steps;
this.applicationRef.tick();
});
}
startUpdates(): Observable<any> {
return Observable.create(observer => {
this.pedometer.startUpdates({
onUpdate: result => observer.next(result)
});
}).pipe(take(25));
}
}
And here's home.component.html:
<StackLayout>
<Label text="Number of steps is:"></Label>
<Label [text]="numSteps"></Label>
</StackLayout>
onUpdate
is called from background thread and Angular is on UI thread. Try this,
startUpdates(): Observable<any> {
return Observable.create(observer => {
this.pedometer.startUpdates({
onUpdate: result => Promise.resolve().then(() => observer.next(result))
});
}).pipe(take(25));
}
Promise.resolve()
forces the block into UI thread.