I've been trying to set up a network plugin as a service on an app to tell whether there's internet or not.
In my example I've set up two components:
- HOME component with the network listener implemented directly in it and
- TEST component that subscribes to an BehaviourSubject observable in networkService
My problem is when trying to destroy the components as I navigate from one to the other. The component where the app is loaded never gets destroyed. Even if I implement something like @HostListener('window:beforeunload') on top of ngOnDestroy().
I have implemented ngOnDestroy on both components to either remove the listener or unsubscribe to the networkServices's observable respectively.
I noticed that if I refresh the app on say Home:
- I navigate to TEST and HOME.ngOnDestroy() does NOT get called.
- When I navigate back from TEST to HOME, TEST.ngOnDestroy() gets called.
If I refresh the app on TEST the same behaviour happens but reversed
- I navigate to HOME and TEST.ngOnDestroy() does NOT get called.
- When I navigate back from HOME to TEST, TEST.ngOnDestroy() gets called.
I've uploaded the project to a public git just in case: https://github.com/jjgl/ionicNetworkCapacitorTests/
but here are the main bits:
HOME
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Plugins, NetworkStatus, PluginListenerHandle } from '@capacitor/core';
const { Network } = Plugins;
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage implements OnInit, OnDestroy {
networkStatus: NetworkStatus;
networkListenerHome: PluginListenerHandle;
async ngOnInit() {
this.networkListenerHome = Network.addListener('networkStatusChange', (status) => {
console.log("Home Page Network status changed", status);
this.networkStatus = status;
});
this.networkStatus = await Network.getStatus();
}
ngOnDestroy() {
console.log('home destroyed')
this.networkListenerHome.remove();
}
}
TEST
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subscription } from 'rxjs';
import { ConnectionStatus, NetworkService } from 'src/app/services/network.service';
@Component({
selector: 'app-test-page',
templateUrl: './test-page.page.html',
styleUrls: ['./test-page.page.scss'],
})
export class TestPagePage implements OnInit, OnDestroy {
subscription : Subscription
private statusOnline : boolean;
constructor(private networkService: NetworkService) {}
async ngOnInit() {
console.log('hola')
this.subscription = this.networkService.onNetworkChange().subscribe((status: ConnectionStatus) => {
this.statusOnline = status == ConnectionStatus.Online ? true : false;
console.log('network change, status:', status);
})
}
ngOnDestroy() {
console.log('test destroyed')
this.subscription.unsubscribe()
}
}
Network Service
import { Injectable, OnDestroy } from '@angular/core';
import { Plugins, NetworkStatus, PluginListenerHandle } from '@capacitor/core';
import { BehaviorSubject, Observable } from 'rxjs';
const { Network } = Plugins;
export enum ConnectionStatus {
Online,
Offline
}
@Injectable({
providedIn: 'root'
})
export class NetworkService implements OnDestroy {
private netStatus: BehaviorSubject<ConnectionStatus> = new BehaviorSubject(ConnectionStatus.Offline);
networkStatus: NetworkStatus;
networkListener: PluginListenerHandle;
constructor() {
this.networkListener = Network.addListener('networkStatusChange', (status) => {
console.log("Service Network status changed", status);
this.networkStatus = status;
let auxStatus = status && status.connected ? ConnectionStatus.Online : ConnectionStatus.Offline;
this.netStatus.next(auxStatus)
});
this.initialState()
}
private async initialState(){
this.networkStatus = await Network.getStatus();
let auxStatus = this.networkStatus && this.networkStatus.connected ? ConnectionStatus.Online : ConnectionStatus.Offline;
this.netStatus.next(auxStatus)
}
public onNetworkChange(): Observable<ConnectionStatus> {
return this.netStatus.asObservable();
}
public getCurrentNetworkStatus(): ConnectionStatus {
return this.netStatus.getValue();
}
ngOnDestroy(): void {
console.log('services destroyed')
this.networkListener.remove();
}
}
Needless to say I'm new to Angular so feel free to point out other things too, all comments are welcome.
PS: I've implemented ngOnDestroy on the networkService, but I'm not calling it from TEST as the service doesn't get reinstantiated when navigating back to TEST after TEST.ngOnDestroy gets called the first time.