Android üzerinde bağlama

Xamarin. Android Uygulamaları, uygulamanın boyutunu azaltmak için bağlayıcı kullanır. Bağlayıcı, hangi derlemelerin gerçekten kullanıldığını, gerçekten kullanıldığını ve hangi üyelerin kullanıldığını belirlemede uygulamanızın statik analizini kullanır. Bağlayıcı daha sonra bir çöp toplayıcıgibi davranır ve başvurulan derlemelerin, türlerin ve üyelerin tüm kapanışına kadar başvurulan derlemeleri, türleri ve üyeleri sürekli arıyor. Ardından, bu kapanışın dışındaki her şey atılır.

Örneğin, Merhaba, Android örneği:

Yapılandırma 1.2.0 boyutu 4.0.1 boyutu
Bağlama olmadan yayın: 14,0 MB 16,0 MB
Bağlama ile yayın: 4,2 MB 2,9 MB

Sonuçları 1.2.0 ' deki özgün (bağlantısız) paketin boyutu %30 ve 4.0.1 içindeki bağlantısı olmayan paketin %18 ' i için bir paket içinde bağlama.

Denetim

Bağlama, Statik Analizedayalıdır. Sonuç olarak, çalışma zamanı ortamına bağlı olan her türlü şey saptanmaz:

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

Bağlayıcı davranışı

bağlayıcıyı denetlemeye yönelik birincil mekanizma, Project seçenekleri iletişim kutusunun içindeki bağlayıcı davranışıdır (Visual Studiobağlama ) açılır. Üç seçenek vardır:

  1. Bağlama (Visual Studio içindeyok )
  2. SDK derlemelerini bağlama (yalnızca SDK derlemeleri)
  3. Tüm bütünleştirilmiş kodları bağla (SDK ve Kullanıcı derlemeleri)

Bağlantı verme seçeneği bağlayıcı kapatır; Yukarıdaki "bağlama olmadan yayın" uygulama boyutu örneği bu davranışı kullandı. Bu, bağlayıcının sorumlu olup olmadığını görmek için çalışma zamanı hatalarının giderilmesi için yararlıdır. Bu ayar genellikle üretim derlemeleri için önerilmez.

Bağlantı SDK 'Sı derlemeleri seçeneği yalnızca Xamarin. Android ile gelen derlemeleribağlar. Diğer tüm derlemeler (kodunuz gibi) bağlı değildir.

Tüm bütünleştirilmiş kodları bağla seçeneği tüm derlemeleri bağlar, bu da statik başvuru olmadığında kodunuzun de kaldırılabileceği anlamına gelir.

Yukarıdaki örnek bağlama ve bağlama SDK derlemeleri seçenekleriyle çalışır ve tüm derlemeleri bağla davranışı ile başarısız olur ve aşağıdaki hata oluşturulur:

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)

Kodu koruma

Bağlayıcı bazen korumak istediğiniz kodu kaldıracaktır. Örnek:

  • Aracılığıyla dinamik olarak çağırdığınız bir kodunuz olabilir System.Reflection.MemberInfo.Invoke .

  • Türleri dinamik olarak örneklediğinizde, türleriniz için varsayılan oluşturucuyu korumak isteyebilirsiniz.

  • XML serileştirme kullanıyorsanız, tiplerinizin özelliklerini korumak isteyebilirsiniz.

Bu durumlarda, Android. Runtime. Preserve özniteliğini kullanabilirsiniz. Uygulama tarafından statik olarak bağlantılı olmayan her üyenin kaldırılması, bu nedenle statik olarak başvurulmayan ancak uygulamanız tarafından hala gerekli olan üyeleri işaretlemek için kullanılabilir. Bu özniteliği bir türün her üyesine veya türüne uygulayabilirsiniz.

Aşağıdaki örnekte bu öznitelik, sınıfının yapıcısını korumak için kullanılır Example :

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

Tüm türü korumak istiyorsanız aşağıdaki öznitelik sözdizimini kullanabilirsiniz:

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

Örneğin, aşağıdaki kod parçasında Example sınıfının tamamı XML serileştirme için korunur:

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

Bazen yalnızca kapsayan tür korunduğu zaman belirli üyeleri korumak isteyebilirsiniz. Bu durumlarda, aşağıdaki öznitelik sözdizimini kullanın:

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

Xamarin kitaplıklarına bağımlılığı almak istemiyorsanız (örneğin, platformlar arası taşınabilir sınıf kitaplığı (PCL) oluşturuyorsanız, özelliğini kullanmaya devam edebilirsiniz Android.Runtime.Preserve . Bunu yapmak için PreserveAttributeAndroid.Runtime ad alanı içinde aşağıdaki gibi bir sınıf bildirin:

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

Yukarıdaki örneklerde, Preserve özniteliği Android.Runtime ad alanında bildirilmiştir; ancak, Preserve bağlayıcı bu özniteliği tür adına göre aradığı için özniteliği herhangi bir ad alanında kullanabilirsiniz.

yanlışbayrak

[Preserve] özniteliği kullanılmıyorsa, bağlayıcının türün kullanıldığını düşündüğü, kod bloğunu çalışma zamanında yürütülmesini engelleyen bir kod bloğu sağlamak genellikle yararlıdır. Bu tekniğin kullanılması için şunları yapabiliriz:

[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

kullanıcı tarafından belirtilen derlemelerin bir kümesinin hiç bağlanmamalıdır ve diğer kullanıcı derlemelerinin AndroidLinkSkip MSBuild özelliğikullanılarak bağlantı SDK 'sı derlemeleriyle atlanmasını sağlamak mümkündür:

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

LinkDescription

@(LinkDescription)@(LinkDescription) , özel bağlayıcı yapılandırma dosyasıiçerebilen dosyalarda kullanılabilir. dosyasýný. Korunması internal gereken Üyeler veya koruma için özel bağlayıcı yapılandırma dosyaları gerekebilir private .

Özel Öznitelikler

Bir derleme bağlandığında, aşağıdaki özel öznitelik türleri tüm üyelerden kaldırılacak:

  • System. kullanımdan kaldırma Teattribute
  • System. Monobelgetationnoteözniteliği
  • System. MonoExtensionAttribute
  • System. Monoınternalnoteözniteliği
  • System. MonoLimitationAttribute
  • System. MonoNotSupportedAttribute
  • System. MonoTODOAttribute
  • System.Xml. MonoFIXAttribute

Bir derleme bağlandığında, aşağıdaki özel öznitelik türleri yayın Derlemeleriyle tüm üyelerden kaldırılacak:

  • System. Diagnostics. hata ayıklama Ggableattribute
  • System. Diagnostics. DebuggerBrowsableAttribute
  • System. Diagnostics. DebuggerDisplayAttribute
  • System. Diagnostics. DebuggerHiddenAttribute
  • System. Diagnostics. DebuggerNonUserCodeAttribute
  • System. Diagnostics. DebuggerStepperBoundaryAttribute
  • System. Diagnostics. DebuggerStepThroughAttribute
  • System. Diagnostics. DebuggerTypeProxyAttribute
  • System. Diagnostics. Debuggervisualizerözniteliği