Skip to content

ngOnDestroy not called on Android back button #923

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
dennis-montana opened this issue Aug 1, 2017 · 12 comments · Fixed by #1728
Closed

ngOnDestroy not called on Android back button #923

dennis-montana opened this issue Aug 1, 2017 · 12 comments · Fixed by #1728

Comments

@dennis-montana
Copy link

dennis-montana commented Aug 1, 2017

We ran into an issue with ngOnDestroy not being called when we use the Android back button.

I've provided a sample application:
https://github.com/dennis-montana/back-button-issue

If you run the app on Android and click the back button you can see that ngOnDestroy isn't called while the native activityDestroyedEvent from Android is being called.
The app is still running in a sleeping state so everything created in ngOnInit is being created again every time a user uses the back button.

If you run the demo app you can see the following output:

### Opened the app 1st time
JS: AppComponent ngOnInit

### Clicked back button
JS: Android activity destroyed

### Opened the app 2nd time
JS: handleResumeEvent
JS: AppComponent ngOnInit

### Clicked back button
JS: Android activity destroyed
JS: Android activity destroyed

### Opened the app 3rd time
JS: handleResumeEvent
JS: handleResumeEvent
JS: AppComponent ngOnInit

### Clicked back button
JS: Android activity destroyed
JS: Android activity destroyed
JS: Android activity destroyed

As you can see the calls are being stacked.

@NickIliev
Copy link

@dennis-montana @spike1292

The observed behaviour is by design and expected as documented here

With router-outlet new instance of the component is created with each navigation and is destroyed when you navigate to another component. The component's constructor and its init hooks will be called every time you navigate to the component and ngOnDestroy() will be called every time you navigate away from it.

With page-router-outlet when you navigate forward, the current page and views are saved in the native navigation stack. The corresponding component is not destroyed. It is cached, so that it can be shown when you go back to the same page. It will still be connected to the views that were cached natively.

@dennis-montana
Copy link
Author

@NickIliev thank you for your reply.

I've read the documentation you've send but it isn't completely clear to me how it describes the Android back button behaviour when there isn't really a component to go back to. When you click back you go the the android home screen.
So when I click back I expect ngOnDestroy to be called or ngOnInit shouldn't be called when I open the app.
Could you elaborate on how to solve this issue?

@NickIliev
Copy link

@dennis-montana perhaps, instead of the Angular life hooks, you can use the NativeScript application events for this case (or directly the Android events).

@vakrilov
Copy link
Contributor

vakrilov commented Aug 8, 2017

I think the solution to that is to handle the activity-destroyed application event and actually kill the angular application when the event is fired. This should call the ngOnDestroy hook for all active components.

@dennis-montana
Copy link
Author

I solved this in our app by directly using the Android application event to call ngOnDestroy.

android.on(AndroidApplication.activityDestroyedEvent, (args: AndroidActivityEventData) => {
   if (args.activity.toString().startsWith('com.tns.NativeScriptActivity')) {
      this.ngOnDestroy();
   }
});

@hdrdiab
Copy link

hdrdiab commented Dec 11, 2017

Hi @dennis-montana ,
Facing the same issue you described above, where exactly have you declared this event ?

@jogboms
Copy link

jogboms commented Dec 11, 2017

@hdrdiab you can place this within your app.component.ts.

@hdrdiab
Copy link

hdrdiab commented Dec 11, 2017

For now i've placed it inside the ngOnInit method, and it is working fine.

@hdrdiab
Copy link

hdrdiab commented Dec 15, 2017

Hi,
The solution @dennis-montana proposed is not working anymore for me.
My component have multiple child components in its view , calling ngOnDestroy on the parent component isn't destroying the children.
Can we can expose the clearCache() method of the NSRouteReuseStrategy ? I think using it will get us a reliable way to kill the angular application.

@nuvoPoint
Copy link

Status on this issue?

@m-abs
Copy link
Contributor

m-abs commented Feb 12, 2019

@nuvoPoint
This is still an issue.

We've run into it in our application.
I've created a test project here:
https://github.com/m-abs/tns-ng-app-lifecycle

Steps to reproduce:

  1. Run the app with tns run android --emulator --bundle --env.aot
  2. Navigate to one of the items. You should see the ngOnInit() logged to console for the components.
  3. Tap the native back button until the app exists. Notice that ngOnDestroy() is NOT logged to the console.

Now if you run npm run apply-patch (this requires bash) and repeat.
Now after step 3 you should see the ngOnDestroy() in the console.

@standevo
Copy link

I wrote an article about this. I solved it in generic way with the decorator.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants