建立网站地图,网站维护正常要多久,手机浏览器下载网页视频,深圳集团网站建设案例作者#xff1a;Dean Ellis 排版#xff1a;Alan Wang 随着 .NET 8 的发布#xff0c;我们引入了一个新系统#xff0c;用于生成访问 Android 资源的 C# 代码。 在 Xamarin.Android、.NET 6 和 .NET 7 中生成 Resource.designer.cs 文件的系统已经被弃用。 新系统生成一个名… 作者Dean Ellis 排版Alan Wang 随着 .NET 8 的发布我们引入了一个新系统用于生成访问 Android 资源的 C# 代码。 在 Xamarin.Android、.NET 6 和 .NET 7 中生成 Resource.designer.cs 文件的系统已经被弃用。 新系统生成一个名为 _Microsoft.Android.Resource.Designer 程序集。其中包含每个程序集的所有最终资源类。
什么是 Android 资源
所有 Android 应用程序都包含一些用户界面资源。它们通常具有 XML 文件形式包含用户界面布局、png 或 svg 文件形式的图像和图标以及包含样式和主题等内容的值。请参阅 Google 文档以深入了解 Android 资源。
Android构建过程的一部分是使用 android sdk 工具 aapt2 将这些资源编译成二进制形式。为了访问这些资源android 公开了一个 API它允许您传递一个整数 id 来检索资源。
SetContentView (2131492864);作为 aapt2 构建过程的一部分将生成文件 R.txt其中包含从资源的“string”名称到 Id 的映射。例如layout/Main.xml 可能映射到 id 2131492864。为了从 C# 访问此数据我们需要一种在代码中公开这些数据的方法。这是由项目 $(RootNamespace) 中的 Resource 类处理的。我们从 R.txt 中获取值并将它们公开在这个类中。在 .NET 7 及之前版本的系统中该类被写入 Resource.designer.cs 文件。它允许用户不需要硬编码 Id 就可以编写可维护的代码。所以上面的调用实际上看起来像这样
SetContentView (Resource.Layout.Main);Resource.Id.Main 将映射到 aapt2 生成的 Id。
为什么要制定这个新系统
旧系统存在一些影响应用程序大小和启动性能的问题。在旧系统中每个 Android 程序集都有自己的一组 Resource 类。所以我们实际上到处都有重复的代码。因此如果您在项目中使用 AndroidX则引用 AndroidX 的每个程序集都会有一个像下面的 Resource 设计器 Id 类
public class Resource {public class Id {// aapt resource value: 0x7F0A0005public const int seekBar 2131361797;// aapt resource value: 0x7F0A0006public const int menu 2131361798;}
}该代码将在每个库中重复。可能还有其他类例如 Layout/Menu/Style都包含这些重复的代码。
此外每个 Resource 类都需要在运行时更新以获得正确的值。这是因为只有当我们构建最终应用程序并生成 R.txt 文件时我们才知道每个资源的 Id。因此应用程序 Resource 类是唯一具有正确 Id 的类。
旧系统使用了名为 UpdateIdValues 的方法该方法在启动时调用。该方法将遍历所有库项目并更新资源 Id 以匹配应用程序中的资源 Id。根据应用程序的尺寸这可能会导致严重的启动延迟。下面是该方法中的代码示例
public static void UpdateIdValues()
{global::Library.Resource.Id.seekBar global::Foo.Foo.Resource.Id.seekBar;global::Library.Resource.Id.menu global::Foo.Foo.Resource.Id.menu;
}更糟糕的是由于 UpdateIdValues 代码的存在修剪器无法删除这些类中的任何一个。因此即使应用程序只使用了一个或两个字段所有这些类都会被保留
新系统对所有这些进行了重新设计以使其适应修剪器几乎以上显示的所有代码都不再生成。 甚至根本不需要 UpdateIdValues 调用。这将改善应用程序的大小和启动时间。
这个新系统是如何运作的
默认情况下.NET 8 Android 将 MSBuild 属性 $(AndroidUseDesignerAssembly) 设置为 true完全关闭旧系统。重新启用旧系统需要手动将此属性更改为 false。
新系统依赖于解析 aapt2 在构建过程中生成的 R.txt 文件。在运行 C# 编译器之前将解析 R.txt 文件并生成新的程序集。该程序集将保存在 IntermediateOutputPath 中并且它会自动添加到应用程序或库的 References 列表中。
对于库项目我们生成引用程序集而不是完整程序集。这向编译器发出信号表明该程序集将在运行时被替换。引用程序集是包含程序级 ReferenceAssemblyAttribute 的程序集。 对于应用程序项目我们生成完整的程序集作为 UpdateAndroidResources 目标的一部分。 这确保我们使用的是 R.txt 文件中的最终值。这个最终的程序集将使用最终的包进行部署。
除了程序集之外还将生成源文件 __Microsoft.Android.Resource.Designer.cs如果您使用 F#源文件为 __Microsoft.Android.Resource.Designer.fs。它包含一个从 Resource 类派生的类。它将存在于项目的 $(RootNamespace) 中。这是使现有代码能够正常工作的纽带 。 因为 Resource 类的命名空间不会改变。对于应用程序项目项目 RootNamespace 中的 Resource 类将从设计器程序集中的 ResourceConstants 类派生。这是为了保持与旧的Resource.designer.cs 文件在应用程序项目中的工作方式的向后兼容性 。
测试表明我们可以将启动时间缩短约 8%。整体封装尺寸大约减少 2%-4%。
我的 NuGet 包仍然有效吗
有些人可能担心通过此更改现有的包引用将停止工作。不用担心新系统引入了一个修剪步骤它将会升级旧系统的程序集引用以使用新系统。这将作为构建的一部分自动完成。此修剪步骤分析所有程序集中的 IL查找使用旧 Resource.designer 字段的位置。然后它将更新这些地方以使用新的Designer程序集属性。它还将完全删除该程序集中的旧Resource.designer。因此即使您使用旧软件包您仍然可以使用这个新系统。
链接器步骤应该涵盖访问 Resource.designer.cs 字段的几乎所有代码。但是如果您遇到问题请在 https://github.com/xamarin/xamarin-android/issues/new/choose 上提交问题。
这个功能将适用于 net8.0-android 之前的任何 Android 程序集引用。
使用新系统构建的包不能与以前版本的.NET Android 一起使用。如果您需要支持 .NET 7 或 Classic Xamarin.Android请考虑使用多目标定位。
NuGet 包作者
如果您正在维护包含 Android 资源的 NuGet 包如果是的话您将需要进行一些更改。首先不需要随 NuGet 一起提供新的 _Microsoft.Android.Resource.Designer.dll。它将由使用 NuGet 的应用程序在构建时生成。
新系统与 Classic Pre .NET Xamarin.Android 以及 .NET 6/7 Android 软件包不兼容。因此如果您想继续支持 Classic Xamarin.Android 以及 .NET 8您将需要对程序集进行多目标操作。如果您不再需要支持 Xamarin.Android 类您可以将项目升级到 .NET Sdk Style 项目并使用以下内容
TargetFrameworksnet7.0-android;net8.0-android/TargetFrameworksClassic Xamarin.Android 将于明年停止支持所以这可能是最佳选择。
如果您需要支持这两个系统您可以使用 Xamarin.Legacy.Sdk 来同时支持 Xamarin.Android 和 net8.0-android。 Xamarin.Legacy.Sdk 是不受支持的所以它只能作为用户升级到 .NET 8 时的权宜之计。有关如何使用此包的详细信息请参阅 Xamarin.Legacy.Sdk GitHub 站点 https://github.com/xamarin/Xamarin.Legacy.Sdk。
从 .NET 6 android 开始AndroidResource、AndroidAsset、AndroidEnvironment、AndroidJavaLibrary、EmbeddedNativeLibrary 和 AndroidNativeLibrary 项不再打包在程序集中。而是在构建时会生成一个 .aar 文件其中包含这些数据并命名为与程序集相同的名称。为了正常工作需要将 .aar 文件与程序集一起发送到 NuGet 中。如果不包含 .aar在运行时将会出现资源丢失错误例如
System.MissingMethodException: Method not found: int .Style.get_MyTheme()如果您在项目中使用 dotnet pack 并在 csproj 中指定 NuGet 属性和设置则默认情况下会包含 .aar。但是如果您使用 .nuspec则需要手动将 .aar 文件添加到要包含的文件列表中。
与 .aar 文件和嵌入文件相关的更改在 OneDotNetEmbeddedResources.md 中有文档记录。
总结
因此新系统会导致软件包大小略微缩小并且启动时间更快。您在应用程序中使用的资源越多影响就越大。