-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
MvxAppStart.cs
126 lines (108 loc) · 4.21 KB
/
MvxAppStart.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MS-PL license.
// See the LICENSE file in the project root for more information.
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using MvvmCross.Exceptions;
using MvvmCross.Logging;
using MvvmCross.Navigation;
namespace MvvmCross.ViewModels
{
#nullable enable
public abstract class MvxAppStart : IMvxAppStart
{
protected readonly IMvxNavigationService NavigationService;
protected readonly IMvxApplication Application;
private int startHasCommenced;
protected MvxAppStart(IMvxApplication application, IMvxNavigationService navigationService)
{
Application = application;
NavigationService = navigationService;
}
public void Start(object? hint = null)
{
StartAsync(hint).GetAwaiter().GetResult();
}
public async Task StartAsync(object? hint = null)
{
// Check whether Start has commenced, and return if it has
if (Interlocked.CompareExchange(ref startHasCommenced, 1, 0) == 1)
return;
var applicationHint = await ApplicationStartup(hint);
if (applicationHint != null)
{
MvxLogHost.Default?.Log(LogLevel.Trace, "Hint ignored in default MvxAppStart");
}
await NavigateToFirstViewModel(applicationHint);
}
protected abstract Task NavigateToFirstViewModel(object? hint = null);
protected virtual async Task<object?> ApplicationStartup(object? hint = null)
{
await Application.Startup();
return hint;
}
public virtual bool IsStarted => startHasCommenced != 0;
public virtual void ResetStart()
{
Reset();
Interlocked.Exchange(ref startHasCommenced, 0);
}
protected virtual void Reset()
{
Application.Reset();
}
}
public class MvxAppStart<TViewModel> : MvxAppStart
where TViewModel : IMvxViewModel
{
public MvxAppStart(IMvxApplication application, IMvxNavigationService navigationService) : base(application, navigationService)
{
}
protected override async Task NavigateToFirstViewModel(object? hint = null)
{
try
{
await NavigationService.Navigate<TViewModel>();
}
catch (System.Exception exception)
{
throw exception.MvxWrap("Problem navigating to ViewModel {0}", typeof(TViewModel).Name);
}
}
}
public class MvxAppStart<TViewModel, TParameter> : MvxAppStart<TViewModel>
where TViewModel : IMvxViewModel<TParameter>
where TParameter : notnull
{
public MvxAppStart(IMvxApplication application, IMvxNavigationService navigationService) : base(application, navigationService)
{
}
protected override async Task<object?> ApplicationStartup(object? hint = null)
{
var applicationHint = await base.ApplicationStartup(hint);
if (applicationHint is TParameter parameter && Application is IMvxApplication<TParameter> typedApplication)
return typedApplication.Startup(parameter);
else
return applicationHint;
}
protected override async Task NavigateToFirstViewModel(object? hint = null)
{
try
{
if (hint is TParameter parameter)
NavigationService.Navigate<TViewModel, TParameter>(parameter).GetAwaiter().GetResult();
else
{
MvxLogHost.Default?.Log(LogLevel.Trace, "Hint is not matching type of {parameterName}. Doing navigation without typed parameter instead.", nameof(TParameter));
await base.NavigateToFirstViewModel(hint);
}
}
catch (System.Exception exception)
{
throw exception.MvxWrap("Problem navigating to ViewModel {0}", typeof(TViewModel).Name);
}
}
}
#nullable restore
}