zoukankan      html  css  js  c++  java
  • 8.在XamarinAndroid上进一步控制包的大小

    在Android上链接

     

    Xamarin.Android应用程序使用链接器来减小应用程序的大小。链接器使用应用程序的静态分析来确定哪些程序集、类型、成员被实际使用。链接器的行为就像一个GC,不断寻找被引用的程序集,类型和成员,直到整个引用的程序集,类型和成员都被找到。没被引用到的类型和程序集都被抛弃掉。

    例如,Hello, Android 示例:

    组态 1.2.0大小 4.0.1大小
    无链接发布: 14.0 MB 16.0 MB
    通过链接发布: 4.2 MB 2.9 MB

    通过链接器处理后的尺寸在1.2.0版本中相当于原来的30%,在4.0.1版本中就只相当于原来的18%。效果非常好啊

    控制

    链接器基于静态分析因此,依赖运行时环境的代码都不会被检测到(比如反射,动态生成对象等等都无法被链接器检测到):

    // To play along at home, Example must be in a different assembly from MyActivity.
    public class Example {
        // Compiler provides default constructor...
    }
    
    [Activity (Label="Linker Example", MainLauncher=true)]
    public class MyActivity {
        protected override void OnCreate (Bundle bundle)
        {
            base.OnCreate (bundle);
    
            // Will this work?
            var o = Activator.CreateInstance (typeof (ExampleLibrary.Example));
        }
    }
    
    

    链接器行为

    控制链接器的主要机制是“ 项目选项”对话框中链接器行为在Visual Studio中)下拉列表有三个选项:

    1. 不要链接在Visual Studio中
    2. 链接SDK程序集仅限Sdk程序集
    3. 链接所有程序集Sdk和用户程序集

    没有链接选项将禁用链接器; 上面的“无链接发布”应用程序大小就是这样的。这种方法对于解决运行时故障很有用,以查看链接器是否做得对。通常不建议在生产版本中使用此设置。

    链接SDK组件选项仅链接 来与Xamarin.Android组件所有其他程序集(如您的代码)不链接。

    链接的所有组件的选择链路上的所有组件,这意味着你的代码如果没有被静态引用则会被删除。

    上面的示例代码可以成功使用“不链接链接SDK程序集”链接选项。但选择“ 链接所有程序集”选项将会失败,并生成以下错误:

    E/mono    (17755): [0xafd4d440:] EXCEPTION handling: System.MissingMethodException: Default constructor not found for type ExampleLibrary.Example.
    I/MonoDroid(17755): UNHANDLED EXCEPTION: System.MissingMethodException: Default constructor not found for type ExampleLibrary.Example.
    I/MonoDroid(17755): at System.Activator.CreateInstance (System.Type,bool) <0x00180>
    I/MonoDroid(17755): at System.Activator.CreateInstance (System.Type) <0x00017>
    I/MonoDroid(17755): at LinkerScratch2.Activity1.OnCreate (Android.OS.Bundle) <0x00027>
    I/MonoDroid(17755): at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (intptr,intptr,intptr) <0x00057>
    I/MonoDroid(17755): at (wrapper dynamic-method) object.95bb4fbe-bef8-4e5b-8e99-ca83a5d7a124 (intptr,intptr,intptr) <0x00033>
    E/mono    (17755): [0xafd4d440:] EXCEPTION handling: System.MissingMethodException: Default constructor not found for type ExampleLibrary.Example.
    E/mono    (17755):
    E/mono    (17755): Unhandled Exception: System.MissingMethodException: Default constructor not found for type ExampleLibrary.Example.
    E/mono    (17755):   at System.Activator.CreateInstance (System.Type type, Boolean nonPublic) [0x00000] in <filename unknown>:0
    E/mono    (17755):   at System.Activator.CreateInstance (System.Type type) [0x00000] in <filename unknown>:0
    E/mono    (17755):   at LinkerScratch2.Activity1.OnCreate (Android.OS.Bundle bundle) [0x00000] in <filename unknown>:0
    E/mono    (17755):   at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (IntPtr jnienv, IntPtr native__this, IntPtr native_savedInstanceState) [0x00000] in
    <filename unknown>:0
    E/mono    (17755):   at (wrapper dynamic-method) object:95bb4fbe-bef8-4e5b-8e99-ca83a5d7a124 (intptr,intptr,intptr)
    
    

    保留代码

    链接器有时会删除掉你本来要保留的代码。例如:

    • 您可能有通过动态反射调用的代码 System.Reflection.MemberInfo.Invoke

    • 如果动态实例化类型,则可能需要保留类型的默认构造函数。

    • 如果使用XML序列化,则可能需要保留类型的属性。

    在这些情况下,您可以使用 Android.Runtime.Preserve 属性用来标记没有被静态引用,但是你的应用程序仍然所需要的成员。您可以将此属性应用于类型的每个成员或类型本身。

    在下面的例子中,这个属性用来保存Example的构造函数

    
    
    public class Example
    {
        [Android.Runtime.Preserve]
        public Example ()
        {
        }
    }
    
    
    

    如果要保留整个类型,则可以使用以下属性语法:

    [Android.Runtime.Preserve (AllMembers = true)]

    例如,在下面的代码片段中,整个Example类都被保留用于XML序列化:

    
    
    [Android.Runtime.Preserve (AllMembers = true)]
    class Example
    {
        // Compiler provides default constructor...
    }
    
    
    

    有时候你想保留某些成员,但是只有保留了包含的类型。在这些情况下,请使用以下属性语法:

    [Android.Runtime.Preserve (Conditional = true)]

    如果您不想依赖Xamarin库(例如,您正在构建一个跨平台的可移植类库(PCL)),你仍然可以使用该Android.Runtime.Preserve 属性。为此,请Android.Runtime名称空间声明一个PreserveAttribute类, 如下所示:

    
    
    namespace Android.Runtime
    {
        public sealed class PreserveAttribute : System.Attribute
        {
            public bool AllMembers;
            public bool Conditional;
        }
    }
    
    
    

    错误标识

    如果不能使用[Preserve]属性,通常需要提供一段预处理指令,以便链接器相信这个类型被使用并保留这个代码块。要使用这个技术我们可以这样做:

    [Activity (Label="Linker Example", MainLauncher=true)]
    class MyActivity {
    
    #pragma warning disable 0219, 0649
        static bool falseflag = false;
        static MyActivity ()
        {
            if (falseflag) {
                var ignore = new Example ();
            }
        }
    #pragma warning restore 0219, 0649
    
        // ...
    }

    linkskip

    可以指定一组用户提供的程序集不被链接处理(以保留整个程序集),同时允许使用AndroidLinkSkip MSBuild属性通过链接SDK程序集行为跳过其他用户程序集

    
    
    <PropertyGroup>
        <AndroidLinkSkip>Assembly1;Assembly2</AndroidLinkSkip>
    </PropertyGroup>
    
    
    

    链接说明

    生成操作可在其中可以包含一个文件中使用 自定义连接配置文件定义需要保留的私有或者内部成员。

    自定义属性

    链接程序集时,将从所有成员中删除以下自定义属性类型:

    • System.ObsoleteAttribute
    • System.MonoDocumentationNoteAttribute
    • System.MonoExtensionAttribute
    • System.MonoInternalNoteAttribute
    • System.MonoLimitationAttribute
    • System.MonoNotSupportedAttribute
    • System.MonoTODOAttribute
    • System.Xml.MonoFIXAttribute

    链接程序集时,下列自定义属性类型将从发布版本中的所有成员中删除:

    • System.Diagnostics.DebuggableAttribute
    • System.Diagnostics.DebuggerBrowsableAttribute
    • System.Diagnostics.DebuggerDisplayAttribute
    • System.Diagnostics.DebuggerHiddenAttribute
    • System.Diagnostics.DebuggerNonUserCodeAttribute
    • System.Diagnostics.DebuggerStepperBoundaryAttribute
    • System.Diagnostics.DebuggerStepThroughAttribute
    • System.Diagnostics.DebuggerTypeProxyAttribute
    • System.Diagnostics.DebuggerVisualizerAttribute
  • 相关阅读:
    paste DEMO合并文件
    diff 文件比较
    grep DEMO
    tr DEMO
    uniq DEMO
    sort DEMO
    定义提示符 PS1 PS4
    MAVEN修改localRepository不起作用
    java数组初始化
    oracle监听服务无法打开
  • 原文地址:https://www.cnblogs.com/jasondun/p/8365983.html
Copyright © 2011-2022 走看看