Nativescript-Angular - 从服务运行回调时 UI 不会更新

0 zone nativescript angular2-nativescript angular

我有一个本地脚本角度应用程序,它运行蓝牙服务来连接到外围设备(设备)。该应用程序会显示一个标签,其中包含一条消息,指示尚未将蓝牙设备连接到运行该应用程序的移动设备。我想做的是更新 UI,以便标签在发生连接时消失(并在发生断开连接时重新出现)。

应用程序组件.tns.html

<StackLayout orientation="vertical" marginBottom="50">
  <Label text="No bluetooth device detected." id="noBluetoothWarning" horizontalAlignment="center" color="#B11" *ngIf="bluetoothDisconnected" marginTop="30" visibility="{{ isBluetoothConnected ? 'collapsed' : 'visible' }}"></Label>
</StackLayout>
Run Code Online (Sandbox Code Playgroud)

应用程序组件.ts

export class NSAppComponent extends AppComponent implements OnInit {


  pageData: Observable;

  ngOnInit() {
    this.bluetoothDisconnected = true;

    let _page = <Page>topmost().currentPage;
    _page.actionBarHidden = true;
    _page.frame.bindingContext = this.pageData;

    let that = this;

    this.bluetoothScanner.connectionStateChangeEvent.subscribe((connectionState) => {
      that.log.debug(`Am I in an angular zone? ${NgZone.isInAngularZone()}`);
      this.ngZone.run(() => {

        that.log.debug(`connectionStateEvent triggered! state is: ${connectionState}`);

        that.bluetoothDisconnected = !connectionState;

        that.pageData.set("isBluetoothConnected", connectionState);

        that.pageData.notify({ object: that.pageData, eventName: Observable.propertyChangeEvent, propertyName: "isBluetoothConnected", value: connectionState });

        this.pageData.notify({ object: that.pageData, eventName: Observable.propertyChangeEvent, propertyName: "bluetoothDisconnected", value: !connectionState });
      })
    });
  }

 constructor( @Inject(LogService) public log: LogService, private ngZone: NgZone) {
      this.pageData = new Observable();
      this.pageData.set("isBluetoothConnected", false);
      this.bluetoothScanner = new BluetoothScanner(...);
  }
}
Run Code Online (Sandbox Code Playgroud)

蓝牙扫描仪.ts

export class BluetoothScanner {
  private connectionState = new BehaviorSubject<boolean>(false);
  ...
    that.connectionState.next(true);
}
Run Code Online (Sandbox Code Playgroud)

您可以看到代码一团糟,但原因是在一个多月的时间里,我一直尝试使用我提到过的每一种可能的操作组合,这些组合可能会帮助我更新 UI,但没有成功。有用。

以下是我之前尝试过但效果不佳的以下方法:

  • 将回调包装在zonedCallback()
  • 将回调包装在ngZone.run()
  • 手动更新组件的变量值(由 tns.html 模板使用)
    • 我不想设置布尔值,而是尝试传递collapsedor的文字字符串visible
  • 用途*ngIfVisibility特性
  • 使用角度的Renderer.listen
  • 使用 nativescript 的Observable类 ( import { Observable } from "data/observable") 以及.notify()在 NSAppComponent 中发出事件 + 监听该事件的功能。BluetoothScanner会延长Observable
  • 使用 rxjsBehaviorSubject对象 ( import { Observable } from "rxjs/BehaviorSubject")
  • 更新变量后使用 Angular 的changeDetectorRef对象来调用 UI 更新
  • 设置一个 Observable 绑定到页面。(请注意,我可能没有正确设置将 Observable 绑定到页面对象[基于我在上面提到的代码中尝试做的事情])。

通过所有这些,我能够更新变量值,但无法更新用户界面。唯一真正更新我的 UI 的是当我在源自 UI 事件(例如按钮点击事件处理程序)的调用中执行变量值更改时。

Nic*_*iev 5

无需在 N+Angular-2 应用程序中使用 Observable - 使用角度绑定技术。我注意到的另一件事是,您还在使用普通 NativeScript 的绑定语法,它与 N+Angular-2 应用程序的绑定语法不兼容。

区别如下: NativeScript Core绑定语法:

visibility="{{ isBluetoothConnected ? 'collapsed' : 'visible' }}"
Run Code Online (Sandbox Code Playgroud)

NativeScript + Angular-2绑定语法:

[visibility]="isItemVisible ? 'visible' : 'collapsed'"
Run Code Online (Sandbox Code Playgroud)

关于如何从回调绑定数据的示例基本上可以在这里找到 ,您应该执行以下操作

export class UsingConnectivityExampleComponent implements OnInit {

public connectionType: string; // use this variable to for binding in your html

constructor(private zone: NgZone) { 
}

ngOnInit() {
    connectivity.startMonitoring((newConnectionType: number) => {
        this.zone.run(() => {
            switch (newConnectionType) {
                case connectivity.connectionType.none:
                    this.connectionType = "None"; // assign value
                    console.log("Connection type changed to none.");
                    break;
                case connectivity.connectionType.wifi:
                    this.connectionType = "Wi-Fi"; // assign value
                    console.log("Connection type changed to WiFi.");
                    break;
                case connectivity.connectionType.mobile:
                    this.connectionType = "Mobile"; // assign value
                    console.log("Connection type changed to mobile.");
                    break;
            }
        });
    });
}
Run Code Online (Sandbox Code Playgroud)

最后使用 ng-2 语法绑定它(该示例显示了单向绑定)

<Label [text]="connectionType"></Label>
Run Code Online (Sandbox Code Playgroud)

有关 NativeScript+Angular-2 中数据绑定的更多信息,请参阅本文档文章

ps 当使用 TypeScript lambda 时,你不需要执行var that = this; 在回调中保留this的范围含义。参考:https://basarat.gitbooks.io/typescript/content/docs/arrow-functions.html