8.在XamarinAndroid上進一步控制包的大小

來源:互聯網
上載者:User

標籤:use   def   nan   tps   class   over   mem   inter   missing   

在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>:0E/mono    (17755):   at System.Activator.CreateInstance (System.Type type) [0x00000] in <filename unknown>:0E/mono    (17755):   at LinkerScratch2.Activity1.OnCreate (Android.OS.Bundle bundle) [0x00000] in <filename unknown>:0E/mono    (17755):   at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (IntPtr jnienv, IntPtr native__this, IntPtr native_savedInstanceState) [0x00000] in<filename unknown>:0E/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

8.在XamarinAndroid上進一步控制包的大小

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.