Skip to content
This repository has been archived by the owner on May 1, 2024. It is now read-only.

[Bug] OnAppearing/OnDisappearing Lifecycle Fixes #6919

Open
PureWeen opened this issue Jul 18, 2019 · 14 comments
Open

[Bug] OnAppearing/OnDisappearing Lifecycle Fixes #6919

PureWeen opened this issue Jul 18, 2019 · 14 comments

Comments

@PureWeen
Copy link
Contributor

PureWeen commented Jul 18, 2019

Description

As a step in the direction of getting #2210 resolved we should first fix OnAppearing/OnDisappearing so that they fire consistently across platform and that we resolve the cases where OnAppearing/OnDisappearing fires at odd times.

Existing Issues
#2240
#2716
#5418
#4986
#4608

Example Ordering issue take from #2210

Example or Ordering Issue

Currently, where MainPage is a TabbedPage you get this:

iOS:

MainPage.CurrentPageChanged event handled
SchedulePage.OnDisappearing() called
SettingsPage.OnAppearing() called

Android:

SchedulePage.OnDisappearing() called
SettingsPage.OnAppearing() called
MainPage.CurrentPageChanged event handled

The issue with the current OnAppearing implementation is that it's a hodge podge of platform hooks and in some cases cross platform. For example currently on iOS OnAppearing fires when ViewDidAppear is called which is OnAppeared not OnAppearing which is inconsistent with Android.

Cases like this on Android TabbedPageRenderer don't make sense

			Element.CurrentPage = Element.Children[position];
			Element.CurrentPage.SendAppearing();

SendAppearing here should just fire from the Element not from the Renderer that way it's cross platform and consistent.

Implementation notes

  • We will most likely need to add a flag in for LegacyLifeCycleEvents like we did with Pavel's original implementation or add a flag for EnableNewLifeCycleEvents that can become default in 5.0.0
  • If new life cycle events are enabled then remove all calls to OnAppearing/OnDisappearing from every single renderer. OnAppearing/OnDisappearing should be 100 percent be a cross platform method that's called because it's more a logical concept then it is a platform one. For example with modal pages when the underlying page is covered that needs to be called. For example with Shell I have it just call disappearing and appearing from the modal calls itself https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Core/Shell/ShellSection.cs#L648
  • Ensure there are UI tests that cover all the issues referenced in the description
@KennyDizi
Copy link

flag for EnableNewLifeCycleEvents that can become default in 5.0.0 => that's sound good!

@AbdellahMobiArchitects
Copy link

We really need this bug fixed for we're having the same issue with a certain page's on appearing method executing even if it's never the active tab

@rs-mobitech
Copy link

Could this be related? I have a System.NullReferenceException in a method that doesn't really have anything in it that could be causing a NullReferenceException.

CardsTabViewModel.OnDisappearing ()
System.NullReferenceException: Object reference not set to an instance of an object

Android: 7.0
Android Build: NRD90M
Manufacturer: vivo
Model: vivo 1714
CrashReporter Key: fa46abc-3677-4ef2-bc43-6f7f13391218
Start Date: 2019-12-26T08:10:50.939Z
Date: 2019-12-26T08:12:43.897Z

Xamarin Exception Stack:
System.NullReferenceException: Object reference not set to an instance of an object
at Japanese.CardsTabViewModel.OnDisappearing () [0x00018] in <460a5aefe005480680b03f394d540b43>:0
at Japanese.CardsTabPage.OnDisappearing () [0x00006] in <460a5aefe005480680b03f394d540b43>:0
at Xamarin.Forms.Page.SendDisappearing () [0x00040] in :0
at Xamarin.Forms.ShellContent.SendDisappearing () [0x0001f] in :0
at Xamarin.Forms.ShellSection.PresentedPageDisappearing () [0x0000f] in :0
at Xamarin.Forms.ShellSection.SendDisappearing () [0x00006] in :0
at Xamarin.Forms.ShellItem.OnCurrentItemChanged (Xamarin.Forms.BindableObject bindable, System.Object oldValue, System.Object newValue) [0x0000a] in :0
at Xamarin.Forms.BindableObject.SetValueActual (Xamarin.Forms.BindableProperty property, Xamarin.Forms.BindableObject+BindablePropertyContext context, System.Object value, System.Boolean currentlyApplying, Xamarin.Forms.Internals.SetValueFlags attributes, System.Boolean silent) [0x0012a] in :0
at Xamarin.Forms.BindableObject.SetValueCore (Xamarin.Forms.BindableProperty property, System.Object value, Xamarin.Forms.Internals.SetValueFlags attributes, Xamarin.Forms.BindableObject+SetValuePrivateFlags privateAttributes) [0x00173] in :0
at Xamarin.Forms.BindableObject.SetValueCore (Xamarin.Forms.BindableProperty property, System.Object value, Xamarin.Forms.Internals.SetValueFlags attributes) [0x00000] in :0
at Xamarin.Forms.Element.SetValueFromRenderer (Xamarin.Forms.BindableProperty property, System.Object value) [0x00000] in :0
at Xamarin.Forms.ShellItem.Xamarin.Forms.IShellItemController.ProposeSection (Xamarin.Forms.ShellSection shellSection, System.Boolean setValue) [0x0002d] in :0
at Xamarin.Forms.Platform.Android.ShellItemRenderer.ChangeSection (Xamarin.Forms.ShellSection shellSection) [0x00006] in <8e6bfbbc42c1411bbf372065ebc4eeb9>:0
at Xamarin.Forms.Platform.Android.ShellItemRenderer.OnItemSelected (Android.Views.IMenuItem item) [0x0006d] in <8e6bfbbc42c1411bbf372065ebc4eeb9>:0
at Xamarin.Forms.Platform.Android.ShellItemRenderer.Android.Support.Design.Widget.BottomNavigationView.IOnNavigationItemSelectedListener.OnNavigationItemSelected (Android.Views.IMenuItem item) [0x00000] in <8e6bfbbc42c1411bbf372065ebc4eeb9>:0
at Android.Support.Design.Widget.BottomNavigationView+IOnNavigationItemSelectedListenerInvoker.n_OnNavigationItemSelected_Landroid_view_MenuItem_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_item) [0x0000f] in <4f5f76e121b14fe1a273d1142e810c70>:0
at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.55(intptr,intptr,intptr)

Thread 17677:
0 java.lang.Object.wait(Object.java:-2)
1 java.lang.Daemons$ReferenceQueueDaemon.run(Daemons.java:153)
2 java.lang.Thread.run(Thread.java:761)

Thread 17678:
0 java.lang.Object.wait(Object.java:-2)
1 java.lang.Object.wait(Object.java:407)
2 java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:188)
3 java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:209)
4 java.lang.Daemons$FinalizerDaemon.run(Daemons.java:208)
5 java.lang.Thread.run(Thread.java:761)

Thread 17679:
0 java.lang.Thread.sleep(Thread.java:-2)
1 java.lang.Thread.sleep(Thread.java:371)
2 java.lang.Thread.sleep(Thread.java:313)
3 java.lang.Daemons$FinalizerWatchdogDaemon.sleepFor(Daemons.java:331)
4 java.lang.Daemons$FinalizerWatchdogDaemon.waitForFinalization(Daemons.java:373)
5 java.lang.Daemons$FinalizerWatchdogDaemon.run(Daemons.java:257)
6 java.lang.Thread.run(Thread.java:761)

Thread 17680:
0 dalvik.system.VMRuntime.runHeapTasks(VMRuntime.java:-2)
1 java.lang.Daemons$HeapTaskDaemon.run(Daemons.java:476)
2 java.lang.Thread.run(Thread.java:761)

Thread 17691:
0 android.os.MessageQueue.nativePollOnce(MessageQueue.java:-2)
1 android.os.MessageQueue.next(MessageQueue.java:328)
2 android.os.Looper.loop(Looper.java:148)
3 android.os.HandlerThread.run(HandlerThread.java:61)

Thread 17693:
0 java.lang.Object.wait(Object.java:-2)
1 java.lang.Thread.parkFor$(Thread.java:2127)
2 sun.misc.Unsafe.park(Unsafe.java:325)
3 java.util.concurrent.locks.LockSupport.park(LockSupport.java:161)
4 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2035)
5 java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:413)
6 java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1058)
7 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1118)
8 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
9 java.lang.Thread.run(Thread.java:761)

Thread 17694:
0 android.os.MessageQueue.nativePollOnce(MessageQueue.java:-2)
1 android.os.MessageQueue.next(MessageQueue.java:328)
2 android.os.Looper.loop(Looper.java:148)
3 android.os.HandlerThread.run(HandlerThread.java:61)

@joshardt
Copy link
Contributor

joshardt commented Jan 2, 2020

@rscholey I don't think your problem has anything in common. You should debug it to see where exactly the NRE occurs. Also have a look on your XAML code.

@dmitrymal
Copy link

It looks like this is still happening. We simply open a modal page Shell.Current.Navigation.PushModalAsync() and then dismiss it using Navigation.PopModalAsync(); Neither OnAppearing nor OnDisappearing event is called on Android.
Also, under some conditions these events get called multiple times.

Are there any suggested work arounds? Can someone point to a pattern how to design/architect the UI without reliable life cycle events such as Appearing and Disappearing?

@joshardt
Copy link
Contributor

joshardt commented Apr 1, 2020

@dmitrymal a workaround for me is to use an event or an observable that fires in a service when the page is closed. This event or observable then triggers the OnAppearing on Android.

@maexsp
Copy link
Contributor

maexsp commented May 4, 2020

Run also into the OnAppearing difference between iOS and Android. iOS is much tool late fired. Please fix it.

@LittleBoxOfChicken
Copy link

Also running into this. This issue is almost a year old and it's still not fixed. disappointing

@akamud
Copy link
Contributor

akamud commented May 18, 2020

This issue is really annoying, indeed. Can you provide more info on why this hasn't been merged yet? Is it a design decision?

@riricardo
Copy link

Just jumped into this issue, really annoying indeed.

@mduchev
Copy link

mduchev commented Aug 13, 2020

Same here.

@samhouts samhouts added this to the 5.0.0 milestone Aug 13, 2020
@samhouts samhouts removed this from the 5.0.0 milestone Nov 2, 2020
@alexreg
Copy link

alexreg commented Sep 30, 2021

No news on this still?

@AlleSchonWeg
Copy link
Contributor

Hi @jfversluis and @jsuarezruiz
i made tests with ios and android. The events are called very different:

Android on setting MainPage = new TabbedPage() //3 Children
TabbedPage: OnCurrentPageChanged
TabbedPage: OnAppearing
Page1 : OnAppearing
Page2 : OnAppearing
Page3 : OnAppearing
->Page1 is shown

Android on clicking Page2
TabbedPage: OnCurrentPageChanged
->Page2 is shown

Android on clicking Page1
Page1 : OnAppearing
TabbedPage: OnCurrentPageChanged
->Page1 is shown

Android on clicking Page2
Page2 : OnAppearing
TabbedPage: OnCurrentPageChanged
->Page2 is shown


iOS on setting MainPage = new TabbedPage() //3 Children
TabbedPage: OnCurrentPageChanged
TabbedPage: OnAppearing
Page1 : OnAppearing
->Page1 is shown

iOS on clicking Page2
TabbedPage: OnCurrentPageChanged
Page2 : OnAppearing
->Page2 is shown

iOS on clicking Page1
TabbedPage: OnCurrentPageChanged
Page1 : OnAppearing
->Page1 is shown

iOS on clicking Page2
TabbedPage: OnCurrentPageChanged
Page2 : OnAppearing
->Page2 is shown

i would say iOS looks ok. But android is really confusing.

@Midnayt

This comment was marked as abuse.

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

No branches or pull requests