Skip to content

Commit 6f7a817

Browse files
committed
Fix DateTime slow first render (#24929)
1 parent e0b3526 commit 6f7a817

File tree

3 files changed

+83
-5
lines changed

3 files changed

+83
-5
lines changed

src/Controls/src/Core/DatePicker/DatePicker.cs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#nullable disable
22
using System;
3+
using System.Threading.Tasks;
4+
using Microsoft.Maui.ApplicationModel;
35
using Microsoft.Maui.Controls.Internals;
46
using Microsoft.Maui.Graphics;
57

@@ -15,7 +17,7 @@ public partial class DatePicker : View, IFontElement, ITextElement, IElementConf
1517
public static readonly BindableProperty DateProperty = BindableProperty.Create(nameof(Date), typeof(DateTime), typeof(DatePicker), default(DateTime), BindingMode.TwoWay,
1618
coerceValue: CoerceDate,
1719
propertyChanged: DatePropertyChanged,
18-
defaultValueCreator: (bindable) => DateTime.Today);
20+
defaultValueCreator: (bindable) => SetDefaultDate(bindable));
1921

2022
/// <summary>Bindable property for <see cref="MinimumDate"/>.</summary>
2123
public static readonly BindableProperty MinimumDateProperty = BindableProperty.Create(nameof(MinimumDate), typeof(DateTime), typeof(DatePicker), new DateTime(1900, 1, 1),
@@ -49,6 +51,22 @@ public partial class DatePicker : View, IFontElement, ITextElement, IElementConf
4951
public DatePicker()
5052
{
5153
_platformConfigurationRegistry = new Lazy<PlatformConfigurationRegistry<DatePicker>>(() => new PlatformConfigurationRegistry<DatePicker>(this));
54+
InitializeDateTimeNowAndSetDate();
55+
}
56+
57+
//TODO: if no better solution is found, move this DateTime initialization somewhere else
58+
/// <summary>
59+
/// Initialize <see cref="DateTime"/> on startup since first call without initializing beforehand takes too much time
60+
/// See: https://github.com/dotnet/maui/issues/24929
61+
/// </summary>
62+
static DatePicker()
63+
{
64+
Task.Run(() =>
65+
{
66+
DateTime dateNow = DateTime.Now;
67+
string dateString = dateNow.ToString();
68+
_isDateTimeInitialized = true;
69+
});
5270
}
5371

5472
/// <include file="../../docs/Microsoft.Maui.Controls/DatePicker.xml" path="//Member[@MemberName='Date']/Docs/*" />
@@ -239,5 +257,41 @@ string IDatePicker.Format
239257
get => Format;
240258
set => SetValue(FormatProperty, value, SetterSpecificity.FromHandler);
241259
}
260+
261+
static bool _isDateTimeInitialized = false;
262+
static DateTime SetDefaultDate(BindableObject bindable)
263+
{
264+
if (_isDateTimeInitialized)
265+
{
266+
return DateTime.Now;
267+
}
268+
return (DateTime)MinimumDateProperty.DefaultValue;
269+
}
270+
271+
/// <summary>
272+
/// If <see cref="DateTime.Now"/> hasn't been initialized, initialize it on worker thread to avoid slowing down first render
273+
/// See: https://github.com/dotnet/maui/issues/24929
274+
/// </summary>
275+
void InitializeDateTimeNowAndSetDate()
276+
{
277+
if (_isDateTimeInitialized)
278+
{
279+
return;
280+
}
281+
Task.Run(() =>
282+
{
283+
DateTime now = DateTime.Now;
284+
_isDateTimeInitialized = true;
285+
//Date might have been changed by client before initialization had a chance to finish
286+
if (Date != MinimumDate)
287+
{
288+
return;
289+
}
290+
MainThread.BeginInvokeOnMainThread(() =>
291+
{
292+
Date = now;
293+
});
294+
});
295+
}
242296
}
243297
}

src/Core/src/Handlers/DatePicker/DatePickerHandler.Android.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@ protected override MauiDatePicker CreatePlatformView()
1919

2020
var date = VirtualView?.Date;
2121

22-
if (date != null)
23-
_dialog = CreateDatePickerDialog(date.Value.Year, date.Value.Month, date.Value.Day);
24-
2522
return mauiDatePicker;
2623
}
2724

src/Core/src/Platform/Android/DatePickerExtensions.cs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
2+
using System.Threading.Tasks;
23
using Android.App;
34
using Android.Content.Res;
5+
using Microsoft.Maui.ApplicationModel;
46

57
namespace Microsoft.Maui.Platform
68
{
@@ -55,7 +57,32 @@ public static void UpdateMaximumDate(this MauiDatePicker platformDatePicker, IDa
5557

5658
internal static void SetText(this MauiDatePicker platformDatePicker, IDatePicker datePicker)
5759
{
58-
platformDatePicker.Text = datePicker.Date.ToString(datePicker.Format);
60+
if (_isDateTimeToStringInitialized)
61+
{
62+
platformDatePicker.Text = datePicker.Date.ToString(datePicker.Format);
63+
}
64+
else
65+
{
66+
InitializeDateTimeToStringAndSetText(platformDatePicker, datePicker);
67+
}
68+
}
69+
70+
static bool _isDateTimeToStringInitialized;
71+
/// <summary>
72+
/// If <see cref="DateTime.ToString()"/> hasn't been initialized, initialize it on worker thread to avoid slowing down first render
73+
/// See: https://github.com/dotnet/maui/issues/24929
74+
/// </summary>
75+
static void InitializeDateTimeToStringAndSetText(MauiDatePicker platformDatePicker, IDatePicker datePicker)
76+
{
77+
Task.Run(() =>
78+
{
79+
string dateString = datePicker.Date.ToString(datePicker.Format);
80+
_isDateTimeToStringInitialized = true;
81+
MainThread.BeginInvokeOnMainThread(() =>
82+
{
83+
platformDatePicker.Text = dateString;
84+
});
85+
});
5986
}
6087
}
6188
}

0 commit comments

Comments
 (0)