Cached Views not reloaded when navigating back: $ionicHistory.goBack()


#1

I have a state defined as follows:

.state('tab.friends-userprofile', {
        url: '/friendsUserprofile/:id',
            views: {
                'tab-friends': {
                    templateUrl: 'templates/social/userprofile.html',
                    controller: 'ProfileCtrl'
                }
            }
})

Think of something like Facebook where you can navigate from one Friend A, to Friend B to Friend C, using the same state (but different instances - as given by the id parameter).

My problem is that when I navigate from Friend A to Friend B to Friend C, then back to Friend B using the back button (i.e. $ionicHistory.goBack()). The cached view of friend B is not returned, instead there is a transition, but the page content stays on Friend C.


#2

Could you provide a minimal example. I’m not 100% sure I follow the problem.


#3

Viewing a person’s profile is a common feature. There is a dedicated state: tab.friends-userprofile as well as a dedicated controller ProfileCtrl.

In a person’s profile there can be links to other friends thus more profiles. Each profile has an id to distinguish.

Here is an example: There are friends A, B and C with respective id’s 1,2,3.
The navigation goes as follows.

  1. Open A’s profile $state.go(tab.friends-userprofile,{id:1}) (view is populated with A’s info via $http)
  2. Open B’s profile $state.go(tab.friends-userprofile,{id:2}) (view is populated with B’s info via $http)
  3. Open C’s profile $state.go(tab.friends-userprofile,{id:3}) (view is populated with C’s info via $http)
  4. Use back button to navigate back $ionicHistory.goBack() at this point I’d expect to see B’s information as it should be cached. Instead there is a transition animation but the data stays the same - i.e. I still see C’s data (as opposed to B).

So in a nutshell, I can navigate forward without a problem, but navigating back doesn’t return the cached views.

Extra info: The state is inside a tab (i.e tab.friends).


#4

In case this can be valuable information with regards to this post TAB like navigation inside a tab (<ion-tab>).

I was attempting to create something like button-bar tabs for lack of a better phrase. This was already inside a tabbed view. To achieve this I put hidden tabs in a <ion-view> tab.
It seems to be working, however, I suspect that maybe I somehow messed the history up and it’s the cause of my issues. This I really doubt, but I’m throwing it out there in case there is something to it.


#5

Hi, @mhartington I finally got a solution to my perculiar problem. With the information I gave you it would have been impossible for you to figure out what the issue was. But I’ll just post it here for anyone who might come across the same issue. I’ll try be as succinct as possible - I actually have a follow up question which is more of an information question though.

I was working on a pattern using a centralised approach to all my all my web requests in the app, which involved using sqlite and events (based on the Google I/O 2010 Rest Talk https://dl.google.com/googleio/2010/android-developing-RESTful-android-apps.pdf). This architecture required a heavy use of events. (more specifically $rootScope.$emit and $rootScope.$on.

The use of $rootScope events seems to be the source of events. I had read somewhere that in angular it is good practice to always destroy $rootScope listeners in the $destroy event of the scope belonging to the controller. I was doing exactly that for my $rootScope events which were carrying notifications of my REST results being ready.

I was able to solve my issue (cached views not being reloaded when navigating back) by deregistering my $rootScope listeners in the $ionicView.beforeLeave event. As soon as I did this my cached views were being restored.

Now here comes the speculation: I’m assuming that therefore my issue was basically a memory leak issue between scopes. From my understanding of the ionic framework, caching works in the sense that controllers are actually never destroyed, therefore my listeners relating to a certain scope were carried on to other scopes, thus leaking memory. Please correct me if I’m wrong.

My question now is just to help me understand. How does the history work, if a controller is never destroyed, how does it connect to a new scope. When you navigate back, is the initialisation code in the controller run again? If so what if you had queried persistent data which has now changed?

To answer my question please use this use case to set context.
Assume that we create a Facebook clone in ionic.

  • Starting from Newsfeed I click on Kholofelo’s name (A)
  • On Kholofelo’s (A) personal feed, I click on his friend Keneiloe’s name (B)
  • On Keneiloe’s (B) personal feed I click on her friend Ivy’s name ©
  • On Ivy’s personal feed I then click the back button (which should take me back to Keneiloe (B))

Let’s assume that The personal feed page is a used for all personal feeds, and as such the same controller, lets call it ProfileController. the state is newsfeed.profile with a parameter id which is the user ID. So in this case, how does the controller and scope get reused.

I know this is very long - but I’ll really appreciate a reply. I can’t seem to find this information and it would really help me if I do get it.


#6

Hi,
did you find a solution? I have exactly the same problem :frowning:


#7

Hi, yes to some extent. See below:

Note, this is as opposed to deregistering on the destroy event, because the Controller is actually reused - so it’s not called and you’ll end up with memory leaks - which is the source of the problem.


#8

have you enabled cache for your state tab.friends-userprofile?
When I click on a item It should create a new instance of the state and create a new DOM with the user data but it doen’t.

The view doen’t change
I have the same conf, with a userId as a parameter for the url and the cache is enabled.


#9

Hi, My cache is not enabled.
Are you getting any errors? Also when you navigate, are you changing you stateParam?

Also, are not listening to any rootScope events i.e. $rootScope.$on?