zoukankan      html  css  js  c++  java
  • Xamarin.Android,Xamarin.iOS, Linking

    Xamarin.Android applications use a linker in order to reduce the size of the application. The linker employes static analysis of your application to determine which assemblies are actually used, which types are actually used, and which members are actually used. The linker then behaves like a garbage collector, continually looking for the assemblies, types, and members that are referenced until the entire closure of referenced assemblies, types, and members is found. Then everything outside of this closure is discarded.

    For example, the Hello, Android sample:

    Configuration 1.2.0 Size 4.0.1 Size
    Release without Linking: 14.0 MB 16.0 MB
    Release with Linking: 4.2 MB 2.9 MB

    Linking results in a package that is 30% the size of the original (unlinked) package in 1.2.0, and 18% of the unlinked package in 4.0.1.

    Control

    Linking is based on static analysis. Consequently, anything that depends upon the runtime environment won't be detected:

    // 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));
        }
    }

    Linker Behavior

    The primary mechanism for controlling the linker is the Linker Behavior drop-down within the Project Options dialog box. There are three options:

    1. Don't Link
    2. Link SDK Assemblies
    3. Link All Assemblies

    The Don't Link option turns off the linker; the above "Release without Linking" application size used this behavior. This is useful for troubleshooting runtime failures, to see if the linker is responsible.

    The Link SDK Assemblies option only links assemblies that come with Xamarin.Android. All other assemblies are not linked.

    The Link All Assemblies option links all assemblies.

    The above example will work with the Don't Link and Link SDK Assemblies options, and will fail with the Link All Assemblies behavior, generating the following error:

    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)

    PreserveAttribute

    The Android.Runtime.PreserveAttribute can be used to explicitly add members to be preserved by the linker, and should be placed on a member when the linker would otherwise remove it. Thus, for the above example to work, we could either place [Preserve] on the constructor:

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

    Or we could use [Preserve(AllMembers=true)] on the type to preseve all members. This is also useful for XML serialization:

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

    falseflag

    If the [Preserve] attribute can't be used, it is often useful to provide a block of code so that the linker believes that the type is used, while preventing the block of code from being executed at runtime. To make use of this technique, we could do:

    [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

    It is possible to specify that a set of user-provided assemblies should not be linked at all, while allowing other user assemblies to be skipped with the Link SDK Assemblies behavior by using the AndroidLinkSkip MSBuild property:

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

    Custom Attributes

    When an assembly is linked, the following custom attribute types will be removed from all members:

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

    When an assembly is linked, the following custom attribute types will be removed from all members in Release builds:

    • 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
  • 相关阅读:
    转:CSS设置HTML元素的高度与宽度的各种情况总结
    Java、mysql、html、css、js 注释&大小写
    Dom4j与sax 简单对比
    转:Java properties | FileNotFoundException: properties (系统找不到指定的文件。)
    转:SAX解析的characters方法被多次调用
    转:HashMap实现原理分析(面试问题:两个hashcode相同 的对象怎么存入hashmap的)
    转:Scanner中nextLine()方法和next()方法的区别
    转:JDBC中关于PreparedStatement.setObject的一些细节说明
    转:Eclipse 各种小图标的含义
    转:Mysql float类型where 语句判断相等问题
  • 原文地址:https://www.cnblogs.com/zjoch/p/4708526.html
Copyright © 2011-2022 走看看