Skip to content

Commit

Permalink
[essentials] use Lazy<T> for Android application-wide values (#7996)
Browse files Browse the repository at this point in the history
* [essentials] use Lazy<T> for Android application-wide values

Context: https://github.com/unoplatform/performance/tree/master/src/dopes/DopeTestMaui

I was reviewing a benchmark/sample that puts lots of labels on the
screen that say "dope" and measures how many per second. Personally, I
would have chosen some other word like `LOL`, so you could have a
`LOLs/s` average. LOL?

Reviewing `dotnet trace` output, I saw:

    1.06s (6.3%) Microsoft.Maui.Essentials!Microsoft.Maui.ApplicationModel.AppInfoImplementation.get_RequestedLayoutDirection()
    4.46ms (0.03%) Microsoft.Maui.Essentials!Microsoft.Maui.ApplicationModel.AppInfoImplementation.get_RequestedTheme()

So approximately 6.3% of the time was spent querying if layouts are
RTL or not? And 0.03% checking dark mode?

I went through `AppInfoImplementation` on Android, and simply used
`Lazy<T>` for every value that queries `Application.Context`. These
values cannot change after the app launches, so they don't need to be
computed on every call.

If these values ever need to match a `Context` for multiple
activities, we should re-evaluate this caching. A dictionary using a
key of `Context.Handle` might work for that case.

We can also remove places with `#if __ANDROID_24__` as they are always
true in .NET 6. Runtime checks using `OperatingSystem` should be used
going forward.

~~ Results ~~

A `Release` build on a Pixel 5 device, I was getting:

    Before: 55.42 Dopes/s
    After:  64.23 Dopes/s

This should help the performance of `Label` in any .NET MAUI
application running on Android.

* Remove IsAndroidVersionAtLeast(17) check

Minimum API level is 21 in .NET 6
  • Loading branch information
jonathanpeppers authored and rmarinho committed Jun 23, 2022
1 parent f4e559a commit b96837a
Showing 1 changed file with 27 additions and 63 deletions.
90 changes: 27 additions & 63 deletions src/Essentials/src/AppInfo/AppInfo.android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,51 +11,21 @@ namespace Microsoft.Maui.ApplicationModel
{
class AppInfoImplementation : IAppInfo
{
public string PackageName => Application.Context.PackageName;
static readonly Lazy<string> _name = new Lazy<string>(() => Application.Context.ApplicationInfo.LoadLabel(Application.Context.PackageManager));
static readonly Lazy<string> _packageName = new Lazy<string>(() => Application.Context.PackageName);
static readonly Lazy<PackageInfo> _packageInfo = new Lazy<PackageInfo>(() => Application.Context.PackageManager.GetPackageInfo(_packageName.Value, PackageInfoFlags.MetaData));
static readonly Lazy<AppTheme> _requestedTheme = new Lazy<AppTheme>(GetRequestedTheme);
static readonly Lazy<LayoutDirection> _layoutDirection = new Lazy<LayoutDirection>(GetLayoutDirection);

public string Name
{
get
{
var applicationInfo = Application.Context.ApplicationInfo;
var packageManager = Application.Context.PackageManager;
return applicationInfo.LoadLabel(packageManager);
}
}
public string PackageName => _packageName.Value;

public string Name => _name.Value;

public System.Version Version => Utils.ParseVersion(VersionString);

public string VersionString
{
get
{
var pm = Application.Context.PackageManager;
var packageName = Application.Context.PackageName;
using (var info = pm.GetPackageInfo(packageName, PackageInfoFlags.MetaData))
{
return info.VersionName;
}
}
}
public string VersionString => _packageInfo.Value.VersionName;

public string BuildString
{
get
{
var pm = Application.Context.PackageManager;
var packageName = Application.Context.PackageName;
using (var info = pm.GetPackageInfo(packageName, PackageInfoFlags.MetaData))
{
#if __ANDROID_28__
return PackageInfoCompat.GetLongVersionCode(info).ToString(CultureInfo.InvariantCulture);
#else
#pragma warning disable CS0618 // Type or member is obsolete
return info.VersionCode.ToString(CultureInfo.InvariantCulture);
#pragma warning restore CS0618 // Type or member is obsolete
#endif
}
}
}
public string BuildString => PackageInfoCompat.GetLongVersionCode(_packageInfo.Value).ToString(CultureInfo.InvariantCulture);

public void ShowSettingsUI()
{
Expand All @@ -67,40 +37,34 @@ public void ShowSettingsUI()
settingsIntent.SetData(global::Android.Net.Uri.Parse("package:" + PackageName));

var flags = ActivityFlags.NewTask | ActivityFlags.NoHistory | ActivityFlags.ExcludeFromRecents;

#if __ANDROID_24__
if (OperatingSystem.IsAndroidVersionAtLeast(24))
flags |= ActivityFlags.LaunchAdjacent;
#endif
settingsIntent.SetFlags(flags);

context.StartActivity(settingsIntent);
}

public AppTheme RequestedTheme
=> (Application.Context.Resources.Configuration.UiMode & UiMode.NightMask) switch
{
UiMode.NightYes => AppTheme.Dark,
UiMode.NightNo => AppTheme.Light,
_ => AppTheme.Unspecified
};
static AppTheme GetRequestedTheme() => (Application.Context.Resources.Configuration.UiMode & UiMode.NightMask) switch
{
UiMode.NightYes => AppTheme.Dark,
UiMode.NightNo => AppTheme.Light,
_ => AppTheme.Unspecified
};

public AppTheme RequestedTheme => _requestedTheme.Value;

public AppPackagingModel PackagingModel => AppPackagingModel.Packaged;

public LayoutDirection RequestedLayoutDirection
static LayoutDirection GetLayoutDirection()
{
get
{
if (!OperatingSystem.IsAndroidVersionAtLeast(17))
return LayoutDirection.LeftToRight;

var config = Application.Context.Resources?.Configuration;
if (config == null)
return LayoutDirection.Unknown;

return (config.LayoutDirection == Android.Views.LayoutDirection.Rtl) ? LayoutDirection.RightToLeft :
LayoutDirection.LeftToRight;
}
var config = Application.Context.Resources?.Configuration;
if (config == null)
return LayoutDirection.Unknown;

return (config.LayoutDirection == Android.Views.LayoutDirection.Rtl) ? LayoutDirection.RightToLeft :
LayoutDirection.LeftToRight;
}

public LayoutDirection RequestedLayoutDirection => _layoutDirection.Value;
}
}

0 comments on commit b96837a

Please sign in to comment.