Nativescript ActivityIndi​​cator无法正确监听忙=变量

时间:2019-03-02 10:38:24

标签: angular nativescript

im创建一个小型应用程序,每当将请求发送到服务器时,我都希望有一个activityIndi​​cator。

因此,在我的UI服务中,我有一个Subject,并且我在ActivityIndi​​catorComponent中正在监听它。结果:它开始“忙”,但是即使指标属性“忙”中的变量为false也不会停止。

那么标识符一次初始化后就以某种方式“不刷新”了吗?

我的UIService

    @Injectable({ providedIn: 'root'})
export class UiService {
    private _drawerState=  new BehaviorSubject<void>(null);
    isLoading = new Subject<boolean>();

    get drawerState() {
        return this._drawerState.asObservable();
    }

    toggleDrawer() {
        this._drawerState.next(null);
    }

    setIsLoading(value: boolean) {
        this.isLoading.next(value);
    }

}

我的Socket服务在Ui服务中调用方法:

export class SocketioService {
socket;

currentRoom: ChatRoom;
message_receiver = new Subject<Message>();
room_receiver = new Subject<ChatRoom>();


constructor(private router: RouterExtensions, private ui: UiService) {
    this.socket = SocketIO.connect("http://localhost:3000");
    console.log("SOCKET: " + this.socket);

    this.socket.on("chat room", (room) => this.onReceivingChatRoom(room));

}


onRequestRoomlist(data) {
    this.ui.setIsLoading(true);
    this.socket.emit("request rooms", data);
}

onReceivingChatRoom(room) {
    this.ui.setIsLoading(false);
    console.log("Received Chat Room");
    this.room_receiver.next(new ChatRoom(room.name, room.description, room.image, room.protection));
}
}

最后我在我的ActivityIndi​​catorComponent中听主题:

export class ActivityIndicatorComponent implements OnInit {

  isLoading: boolean;

  constructor(private ui: UiService) { }

  ngOnInit() {
    this.ui.isLoading.subscribe(
        (value: boolean) => {
          this.isLoading = value;
        }
    )
  }

}

这是ActivityIndi​​catorComponent的xml

<ActivityIndicator #indicator row="1" col="1" width="50" height="50" busy="{{isLoading}}" color="#6495ed"></ActivityIndicator>

2 个答案:

答案 0 :(得分:1)

套接字可能在Angular区域之外运行,因此,更改变量后,它将向您的主题发送更新,并且由于它在区域之外,因此不会触发更改检测。

这可以通过两种方式解决:

  1. 您已解决的问题,通过手动调用detectChanges()
  2. 通过在ngZone.run(() => {/* code */});的角区域内跑步

您还可以使用此可观察的运算符来确保代码在区域内运行。

import { NgZone } from '@angular/core';
import { Observable } from 'rxjs/Observable';

export function enterZone(zone: NgZone) {
  return <T>(source: Observable<T>) =>
    new Observable<T>(observer =>
      source.subscribe({
        next: (x) => zone.run(() => observer.next(x)),
        error: (err) => observer.error(err),
        complete: () => observer.complete()
    })
   );
}

因此您可以使用:this.ui.isLoading.pipe(enterZone(ngZone)).subscribe()。甚至更好,您可以在服务中定义:

isLoading$ = this.isLoading.pipe(enterZone(ngZone))

因此,您可以确定正在订阅isLoading$的任何内容实际上都在Angular区域内运行。

编辑:

带有可观察到的UIService的示例:

@Injectable({ providedIn: 'root'})
export class UiService {
    private _drawerState=  new BehaviorSubject<void>(null);
    isLoading = new Subject<boolean>();
    isLoading$ = this.isLoading.pipe(enterZone(this.ngZone));

    get drawerState() {
        return this._drawerState.asObservable();
    }

    constructor(private ngZone: NgZone) {}

    toggleDrawer() {
        this._drawerState.next(null);
    }

    setIsLoading(value: boolean) {
        this.isLoading.next(value);
    }

}

答案 1 :(得分:0)

我通过使用ActivityIndi​​catorComponent中的ChangeDetectorRef对其进行了修复。

在收到新的价值后,我叫changeRef.detectChanges();的订阅生效了