Alex
Alex

Reputation: 610

App.xaml.cs ctor is called when OnResume() should be called

If I navigate in my App and go back to the Android LaunchScreen with the HomeButton the OnSleep() Hook is called, which is fine. If I navigate back into the App using the Android TaskManager OnResume() is called. If I navigate in my App with the Hardware BackButton then also OnSleep() is called which is fine, but if I navigate back into my app then the OnCreate Method in the MainActivity is called which recreated the App.

        global::Xamarin.Forms.Forms.Init (this, bundle);
        DisplayCrashReport();
        LoadApplication (new Gtue.Mobile.App ());

That should not happen. In the ctor of App.xaml I initialize stuff which only should be initialized once. I tried every LaunchMode for the MainAcitivity, nothing helped.

Is there a way to find out if the App was already initialized?

Upvotes: 2

Views: 1048

Answers (2)

WickedW
WickedW

Reputation: 2601

I came across this issue when observing my App.xaml.cs constructor was being called when I was pressing the home button on my Android device and then clicking my app.

The well detailed answer above details the correct "anticipated behaviour", but this was not the case for me.

I was getting this kind of flow when using the home button or back button -

**On Debug Start**
MainActivity:OnCreate
XF:AppCtor
XF:OnStart
MainActivity:OnResume

**Press Home Button**
MainActivity:OnPause
XF:OnSleep

**Launch App via Click on App Icon**
MainActivity:OnCreate
XF:AppCtor

Searching eventually led me to -

App restarts rather than resumes

Which in turn resulted in the following Xamarin code at the top of MainActivity OnCreate -

        if (!IsTaskRoot)
        {
            string action = Intent.Action;
            if (Intent.HasCategory(Android.Content.Intent.CategoryLauncher) &&
                !string.IsNullOrEmpty(Intent.Action) &&
                action == Android.Content.Intent.ActionMain)
            {
                Finish();
                return;
            }
        }

Which seems to solve the initial reload at least.

I also combined this with -

 LaunchMode = LaunchMode.SingleTask

To stop some double activity shenanigans when clicking on a notification in notification screen.

Upvotes: 0

York Shen
York Shen

Reputation: 9084

Your App class extends from Xamarin.Forms.Application and the Xamarin.Forms.Application life cycle is bind with the Activity life cycle. You could find it in the source code :

async Task OnStateChanged()
{
    if (_application == null)
        return;

    if (_previousState == AndroidApplicationLifecycleState.OnCreate && _currentState == AndroidApplicationLifecycleState.OnStart)
        _application.SendStart();
    else if (_previousState == AndroidApplicationLifecycleState.OnStop && _currentState == AndroidApplicationLifecycleState.OnRestart)
        _application.SendResume();
    else if (_previousState == AndroidApplicationLifecycleState.OnPause && _currentState == AndroidApplicationLifecycleState.OnStop)
        await _application.SendSleepAsync();
}

So you just need to care about your Activity's life cycle. When you touch the HomeButton your application don't remove the MainActivity from the task's stack and the MainActivity will be available when you re-enter the app, so it didn't execute the OnCreate method.

When you touch the HomeButton :

[0:] MainActivity OnPause
[0:] MainActivity OnStop
[0:] Forms App OnSleep

When you use the Android TaskManager open your application :

[0:] MainActivity OnRestart
[0:] Forms App OnResume
[0:] MainActivity OnResume

But when you touch the hardware BackButton, the MainActivity will be removed from the task's stack :

[0:] MainActivity OnPause
[0:] MainActivity OnStop
[0:] Forms App OnSleep
[0:] MainActivity OnDestroy

When the MainActivity is destoryed, your application will dispose resource and it including your Gtue.Mobile.App instance. And you could see the source code about OnDestroy() method :

protected override void OnDestroy()
{
    PopupManager.Unsubscribe(this);
    _platform?.Dispose();

    // call at the end to avoid race conditions with Platform dispose
    base.OnDestroy();
}

So the next time when you open your application, it is necessary to recreated the App class. Actually, the App did only be initialized once.

Upvotes: 3

Related Questions