Skip to content

ngOnDestroy not called on Android back button #923

Closed

Description

@dennis-montana

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.

Activity

  1. NickIliev commented on Aug 7, 2017

    @NickIliev

    @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.

  2. dennis-montana commented on Aug 7, 2017

    @dennis-montana
    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?

  3. NickIliev commented on Aug 7, 2017

    @NickIliev

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

  4. vakrilov commented on Aug 8, 2017

    @vakrilov
    Contributor

    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.

  5. dennis-montana commented on Aug 9, 2017

    @dennis-montana
    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();
       }
    });
  6. hdrdiab commented on Dec 11, 2017

    @hdrdiab

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

  7. jogboms commented on Dec 11, 2017

    @jogboms

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

  8. hdrdiab commented on Dec 11, 2017

    @hdrdiab

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

  9. hdrdiab commented on Dec 15, 2017

    @hdrdiab

    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.

  10. m-abs commented on Feb 12, 2019

    @m-abs
    Contributor

    @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.

  11. ghost removed on Apr 15, 2019
  12. stanporubin commented on Sep 26, 2019

    @stanporubin

    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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions