Chris Rae
Chris Rae

Reputation: 5665

Reliably detect when view not active in Ionic

I have a view in a mobile Ionic app which regularly refreshes data in the background. I want this to stop happening when:

  1. This view is not the active view
  2. The app is in the background

Right now I accomplish these with:

$scope.$on('$ionicView.beforeLeave', pauseUpdates);
$scope.$on('$ionicView.enter', restartUpdates);
document.addEventListener("pause", pauseUpdates, false);
document.addEventListener("resume", restartUpdates, false);

However, this introduces an edge case where the user goes into my view, then goes back to another view, puts the app in the background and then switches back to it (I restart updates, when I shouldn't have).

Before I go making some sort of isNotCurrentView variable to track - am I going about this entirely the wrong way? Is there some neater way to track my status? I always secretly felt that using addEventListener was a not-very-Angular way to go about this...

Upvotes: 0

Views: 832

Answers (2)

Chris Rae
Chris Rae

Reputation: 5665

After a bit of digging around I've found a more elegant solution to this. As per https://forum.ionicframework.com/t/best-way-to-intercept-events-like-cordova-resume-and-pause-in-ionic/4720/5, a good way to deal with these is to add document-level handlers which fire root-scope broadcasts:

.run(function ($ionicPlatform, $rootScope) {

    $ionicPlatform.ready(function () {
        document.addEventListener("deviceready", onDeviceReady, false);
    });

    function onDeviceReady() {

        console.log('run() -> onDeviceReady');

        document.addEventListener("pause", function (event) {
            console.log('run() -> cordovaPauseEvent');
            $rootScope.$broadcast('cordovaPauseEvent');
        });

        document.addEventListener("resume", function (event) {
            console.log('run() -> cordovaResumeEvent');
            $rootScope.$broadcast('cordovaResumeEvent');
        });
    }
}

Inside your actual controller, you can then handle these like so:

$scope.$on('cordovaPauseEvent', pauseTotalsUpdates);

When the view using your controller is no longer active, Ionic's view caching will keep the controller in memory but will de-activate its $scope. This means that your controller won't run pause/resume events unless it's the active controller. Remember to attach the $on event to $scope and not $rootScope, as that is not detached when your controller goes out of view.

Upvotes: 2

beaver
beaver

Reputation: 17647

Do you know that you can rely on $stateChangeStart event from https://github.com/angular-ui/ui-router/wiki ?

So you can keep your current state/view using this handler in your controller(s):

$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
...
});

Also you could use cordova-plugin-background-mode to track events like "activation of bkg mode" (see onactivate) or "resuming from bkg mode" (see ondeactivate).

Upvotes: 0

Related Questions