As one of the authors of ReactiveUI, I have found that Xamarin.Forms does not provide the requisite view life cycle hooks to enable the framework to manage the activation and deactivation of resources in response to the comings and goings of views.
Specifically, I have found these problems:
Page.Appearing
actually fires in response to ViewDidAppear
on iOS. One of ReactiveUI's benefits is its code-based, type-safe binding infrastructure. Appearing
is the only hook we can use to get stuff on the screen, but it fires too late on iOS, so there is a brief period where the screen is not populated with data. I have already attempted to start a discussion here, but it seemed to stagnate.View
, there is no way to tell when that View
appears and disappears from the screen. There is no View.Appearing
or View.Disappearing
events as there is for Page
. It might seem appropriate to therefore search up the visual tree for the Page
and hook into that. However, this is inefficient (but perhaps that's inevitable) and there is no means of knowing when the Page
itself changes. There is no PageChanged
event, and PropertyChanged
does not fire in response to the Page
changing.Page.Appearing
should fire in response to ViewWillAppear
on iOS. Moreover, there should be Page.Appeared
and Page.Disappeared
counterparts. Yes, this is potentially breaking to people who are hooked into Appearing
and rely on it firing in response to ViewDidAppear
on iOS. However, that behavior has always been incorrect and the fix for these people is literally to change Appearing
to Appeared
(or hold off on the XF upgrade).Appearing
, Appeared
, Disappearing
, Disappeared
to View
and have them Just Work. Failing that, ensure there is a hook by which framework authors can know the hosting Page
for a View
has changed. Perhaps a specific PageChanged
event, or just ensuring PropertyChanged
works as expected in this scenario.The use case here is to give framework authors what they need to facilitate the creation of self-sufficient, standalone, encapsulated components by framework consumers. I specifically work on ReactiveUI, but other framework authors will/have run into the same issues.
ModEdit - Spec incoming ASAP
Posts
I like this. Would you be willing to create a table like so:
Also on further thought I think we would probably need to have a "Compatibility" mode for anyone updating and not wanting to port to the new behavior.
A default compatibility mode will be essential. I have never come across any app that doesn't depend on OnAppearing at some point. While it might not cause any issues, it has the potential to cause havoc on existing apps.
Yup, mandatory. Should probably look something like
Old apps can just put that in their App.cs to restore the legacy behavior.
Hope you make this a priority because I need to start a new app and I want to do
Xamarin.Forms.Page.UseLegacyLifecycleEvents = false;
Having said that, I'm not sure if Android or UWP event cycles are 100% translatable to iOS. Not sure what kind of issues this could create for people.
We really need to make sure we have a good idea of what all the old/new events should be. I think we wrote a spec on this like a year ago but I am afraid we lost the data in the migration to microsoft services...
This is the best I have. Not everything is 100% translatable. Will require tapping into events on other objects to probably detect an about to disappear. From the Android documentation, OnDetachedToWindow states it no longer has a surface to draw on at the point of OnDetachedToWindow, hence I assume its already gone at this point. The OnGlobalLayout is apparently the only point at which we can detect if Android has finished doing its layout, as you could tap into OnDraw but it can be recursive, so you would never know when it finished.
Disappearing is easy enough to emulate on platforms that need it. Basically emit when its removed from the logical hierarchy.
@AdamP my thinking was that if the platform doesn't have a more specific hook, then the same hook resolves to both events. For example, on Android
OnAttachedToWindow
would fireAppearing
and thenAppeared
immediately after. From the viewpoint of the consumer, I don't think it matters. As long as both events are raised in the right order and they correlate to the best possible hook in the underlying platform.I know for a fact that setting up data in
Appearing
on Android (i.e. in response toOnAttachedToWindow
) does not present the same problem as on iOS (data appearing too late).@KentBoogaart - if a platform doesn't have a specific hook, I would go down the path of emulating it.
The problem is if you don't have all platforms behaving exactly same in this scenario it can lead to discrepancies in a XF app, that will be nothing but an absolute pain to then rectify from the app developers view e.g. me
Say data loading too early, or too late, causing a not so smooth UI experience, or something like that.
Appeared could be handled by a variety of hooks. Draw is a bad one since overriding draw has performance implications, but the layout hook might work. We could even go as stupid as a timer if we want to be as loose as saying "Appeared will happen some time shortly after the object is on screen but not always immediately so"
@AdamP As someone who also develops apps for a day job, I'm struggling to understand why emulation would lead to fewer headaches for me as an app developer. I don't think it's realistic to have exact same behavior across all platforms, but if we were trying to get as close to that as possible then we could just change iOS to use
ViewWillAppear
instead ofViewDidAppear
.That said, if a dependable emulation can be found I'm all for it. What worries me is trying to get too clever and creating more problems than we started with. I can imagine the underlying platform evolving and breaking the emulation, perhaps with no recourse. If we're only using life cycle hooks that are officially supported by the platform, that feels a lot safer to me.
I think we just need to be consistent in how we define what these events are.
Appearing: The view is about to appear. This is a good time to set up update events, etc. Data updates should be enqueued here, but initial data should already be loaded.
Appeared: The view is visible on screeen, feel free to screenshot it. There is no guarantee that the view only just became visible, just that this happens after Appeared and before DIsappearing with a (strong) bias towards as close to Appearing as possible on the platform.
Disappearing: The view has been removed from the Xamarin.Forms logical hierarchy, either by direct or indirect action by the user. The view MAY still be be visible on screen.
Disappeared: The view is no longer visible on screen.
It's worth noting that in the iOS case I am actually suggesting that we do not use ViewWillDisappear here. I do not believe sticking to that particular callback on iOS lends any benefit but having it uniform and predictable as possible in this case is preferable.
Too complex for leave 4 events. I think currently 2 events good enough already. could we let things more simple and easy for now?(for UWP especially)
@huangjinshe We definitely need more than two events. I think @TheRealJasonSmith summed up the scenarios pretty well.
I agree with the events, one of the thing to take notice is the hierarchy the events fire, so if i m child of a NavPage, nav page should fire first, then the child page. This is more complex that it seems in order to be consistent between platforms.
@huangjinshe
You can use the events, but you don't have to use it.
For me, this is a real problem and a good proposal (that should be accepted)
First, I want to post a reminder that "+1" style comments are not allowed. There is a like button if you agree with something.
Second, I want to say as a team we think this is a great proposal. It's something we have actually wanted for a while. I think this proposal still needs to work out the following things:
My personal opinion here is we probably shouldn't attempt to guarantee ordering in a hierarchical sense. It's quite likely we will end up having to fight the underlying platforms quite strongly. The only thing we should consider doing is making sure that its consistent that pages ALWAYS get these events, even if, for example, their parent is what is actually removed and the underlying toolkit doesn't end up triggering the events because of that.
Once we have a spec I will put a link to it (as a gist) in the OP.
Continuing on the lifecycle conversation. I think there's a strong need for one (possibly two) more beyond what's already accepted.
I'd like to propose at minimum
OnRemoved
and possiblyOnRemoving
(but maybe not necessary). The reason for this is for cleanup when a Page is being removed from the navigation hierarchy.I've created a separate proposal, but it really does belong here.
https://forums.xamarin.com/discussion/85745/add-onpopped-method-to-page
Intended Use Case
The biggest reason for this is to solve the issue whereby we need to clear Behaviors from a VisualElement, especially when those behaviors are added via xaml. If we tap into the existing methods (even the ones proposed above), we would be cleaning up our page when a new page is pushed over top and not limited to when the page is popped.
Example:
Is it possible to also unify
NavigationStack
behaviour while making this change?Last time I checked (some time ago), the behaviour on Android was:
Push
a page toNavigationStack
, thenPop
it. Result: it isn't inNavigationStack
anymorePush
a page toNavigationStack
, thenTap navigation back button
. Result: it's still inNavigationStack
, until another page is pushed.That makes sense because one might go forward in time when going back. Like browsers do today.
However, when you pop a view, it is closed forever - just like a modal dialog.
Please bring back that Like button! It's gone in the Evolution forum.
(now I have a Like button on my own post, but not on others')
I agree with @ChaseFlorell that we need to distinguish between when a page was popped or another has been pushed over it. In the former case you need to clean up, in the latter not.
I also opened a bug a few years back that Appearing/Disappearing were raised in a different order on iOS and Android when you pushed/popped a page. IMHO it is very important that the order is consistent over platforms. Unfortunately the bug got closed (not fixed) and I can't search for closed bugs on bugzilla.
+1
In all seriousness, in case it's not this way for others, the only place I do see the like button is on my own posts
We're working on fixing it.
It's a Vanilla Forums issue.
/backontopic
@DanielL i think it depends where we check, the NavigationStack can be update after the animation finished vs being updated before, but yes we can fix that i just also found this issue while working on MacOS branch.
@rmarinho
Fixing that bug would be very useful for me, eg. I could implement navigation back event.
On Android when navigation is used (back icon), it isn't removed from navigation stack at all. It's removed only if another page is pushed.
Please fix this.
Note that I've posted an interim, hacky workaround for the iOS
ViewDidAppear
problem here: http://kent-boogaart.com/blog/hacking-xamarin.forms-page.appearing-for-iosthat's awesome! @KentBoogaart
How's the progress ?
Just for info please note that people are coming to xamarin from other technologies WPF, WinForms, WebForms, Js ... Web , it would be nice to have same names, page loaded loaded ..
We really need a few other hooks, Create, Created, Destroyed, Destroying.
This may look like the Android Activity lifecycle.
Or the Android Fragment lifecycle:
And the Disappearing or Destroyed (or Destroying) hook should also allow the app to save the view's state (preferably a page's state) in a dictionary like object (Android's bundle concept) and that same object should be given back to the view's resurrected object if the app is being restarted.
But for all of this to work, Forms needs to take control of the app's lifecycle and retain and restore Page / View states and navigation stacks upon application restarts. Unless this is implemented, almost none of the lifecycle hooks give us much advantage...
I feel like it might be important to note that Google has looked into issues with lifecycle management on Android and came up with this for their new Architecture components.

They even provide new ways to track the lifecycle state and, thus, allow you to determine whether or not a specific function should run at this time.
e.g.:
I think the most important thing is to have every lifecycle event from every platform fire some callback in the page. I think it's fine if, as a consequence, there are some Page callbacks events that never fire on some platforms. It would be important to document that, obviously, maybe with a table of what platform event corresponds to which Page event.
I like this idea.
I just ran into an issue where the lateness of iOS was a problem. I had to the customer renderer hack Kent wrote up to get it working with viewillappear.
Do we know if this will ever change?
I'd say yes.
See David Ortinau's response down at the bottom of this Bugzilla issue I filed related to this: https://bugzilla.xamarin.com/show_bug.cgi?id=60739
Glad to see it is an item on their list. I'm a little concerned about this part though:
"That proposal has been in spirit accepted, but needs a spec and someone to take on the work and generate a pull request."
What if no one takes on the work?
@ChaseFlorell re
Perhaps it is more robust to ensure that all important view state is reflected in bound properties, so that it is easy to restore page to desired state in OnAppearing? IIRC, in native programming, it can happen that user has left your app, the OS has suspended it, and then returned to your app, re-creating all the views/fragments on the native nav stack. Is the Xamarin Nav stack susceptible to this? It might be a fragile illusion to rely on preservation of all details of a view on nav stack.
Re knowing when view has appeared on Android.
@AdamP - OnAttachedToWindow - this is a feature of Android
NativeActivity
which is a special activity convenient when using NDK to write in C/C++. Can this be adapted for use with Xamarin.Forms.Platform.Android.FormsAppCompatActivity, which is what I see as base of main activity on Android?So far, I haven't found any solution other than overriding a View's
OnDraw
(as you mentioned), with a bool to only do the action once. Or perhaps instead put code in override ofDraw
. For completeness, here is how I see it:Details:
Kent Boogart's hack for iOS, to do an action before page appears:
https://kent-boogaart.com/blog/hacking-xamarin.forms-page.appearing-for-ios
My updated code for Android, to do an action after page is drawn the first time:
https://stackoverflow.com/a/52748913/199364
Combining these two hacks, with the existing behavior (which is "after appearing" on iOS, "before appearing" on Android), yields both before and after for the two platforms.
It should be fairly easy to incorporate both techniques into an implementation with "WillAppear" and "DidAppear".
So this hackery isn't needed by app programmers.
I'm not familiar with UWP.
@SteveShaw.5557 thank you for your answer .... can you please explain where we have to put that hacks? thank you very much!