Xamarin.Forms 的 Linker 選擇
這裡的相關範例將會使用 Xamarin.Android 模式下來操作,當然,同樣的操作,在 Xamarin.iOS 操作方式也是一樣。
將範例專案進行不同的 Linker 設定
- 使用 Visual Studio 2015 打開範例專案
DoggyMobileBE.sln
- 使用滑鼠雙擊
DoggyMobileBE.Droid
專案 >Properties
節點 - 當出現 Xamarin.Android 的專案屬性頁面,請點選
Android Options
>Linker
您可以從標籤Linking:
下方的下拉選單,選擇:- None這個選項將會關閉
Linker
的功能,也就是說,當在這個模式下的時候,所產生的 APK 檔案體積是最大的。若您選擇其他模式,會造成您的應用程式異常閃退,建議可以先切換到這個模式下,確認在這個模式下產生的程式不會有任何異常閃退,接著再進行了解是要把哪個組件或者型別排除在Linker
模式之外。 - Sdk Assemblies Only在這個模式下,僅僅會針對來自於
Xamarin.Android
的組件進行Linker
靜態分析,這些組件您可以參考網址https://developer.xamarin.com/guides/cross-platform/advanced/available-assemblies/
。而不在這清單內的組將,將不會進行Linker
處理。 - Sdk and User Assemblies這個模式會將產生最小檔案體積的 APK 檔案,所有的組件都會進行
Linker
分析,當然,檔案變小,就代表了程式的載入時間變短、加快執行效率。
比較範例專案的不同 Linker 模式下,產生的 APK 檔案
在這裡設定這個 Xamarin.Android 專案使用的
Debug
組態模式,分別進行 None
, Sdk Assemblies Only
,Sdk and User Assemblies
這三種 Linker 模式的建置與產生 APK,得到結果如下:None | Sdk Assemblies Only | Sdk and User Assemblies | |
---|---|---|---|
APK檔案大小 | 60MB | 21.5MB | 17.8MB |
您可以從上面的表格中,看到採用
Sdk and User Assemblies
Linker 模式下所產生出來的 APK,其檔案體積最小,可是,很不幸的,當您使用這個模式產生的 APK 檔案,安裝到使用者手機上之後,一旦執行,就會閃退。
要如何解決此一問題,後面將會有建議一個步驟,不過,先來看看這三種模式下產生的 APK 檔案內容,底下的內容,為使用 zip 解壓縮軟體,把 APK 檔案解壓縮之後,使用 DIR 指令查看
assemblies
目錄下所得到的結果。None
2016/07/19 上午 12:17 22,016 DoggyMobileBE.dll
2016/07/29 下午 10:06 931 DoggyMobileBE.dll.config
2016/07/29 下午 10:05 3,781 DoggyMobileBE.dll.mdb
2016/07/29 下午 10:06 90,112 DoggyMobileBE.Droid.dll
2016/07/29 下午 10:06 9,078 DoggyMobileBE.Droid.dll.mdb
2016/01/18 下午 03:36 13,824 FormsViewGroup.dll
2016/06/20 下午 03:37 114,688 Java.Interop.dll
2016/06/20 下午 02:03 44,745 Java.Interop.dll.mdb
2016/06/20 下午 03:37 30,720 Microsoft.CSharp.dll
2016/06/20 下午 03:36 10,126 Microsoft.CSharp.dll.mdb
2016/07/07 上午 11:50 327,704 Microsoft.WindowsAzure.Mobile.dll
2016/07/07 上午 11:50 93,208 Microsoft.WindowsAzure.Mobile.Ext.dll
2016/06/20 下午 03:40 22,217,216 Mono.Android.dll
2016/06/20 下午 03:40 7,604,642 Mono.Android.dll.mdb
2016/06/20 下午 03:37 1,350,144 Mono.CSharp.dll
2016/06/20 下午 03:36 438,175 Mono.CSharp.dll.mdb
2016/06/20 下午 03:37 3,646,976 mscorlib.dll
2016/06/20 下午 03:36 1,496,781 mscorlib.dll.mdb
2014/08/03 下午 08:33 444,928 Newtonsoft.Json.dll
2016/06/20 下午 03:37 6,144 System.Collections.Concurrent.dll
2016/06/20 下午 03:37 6,144 System.Collections.dll
2016/06/20 下午 03:37 270,848 System.ComponentModel.Composition.dll
2016/06/20 下午 03:36 137,422 System.ComponentModel.Composition.dll.mdb
2016/06/20 下午 03:37 4,608 System.ComponentModel.dll
2016/06/20 下午 03:37 869,376 System.Core.dll
2016/06/20 下午 03:36 359,097 System.Core.dll.mdb
2016/06/20 下午 03:37 4,608 System.Diagnostics.Debug.dll
2016/06/20 下午 03:37 4,608 System.Diagnostics.Tools.dll
2016/06/20 下午 03:37 1,806,336 System.dll
2016/06/20 下午 03:36 768,066 System.dll.mdb
2016/06/20 下午 03:37 6,656 System.Dynamic.Runtime.dll
2016/06/20 下午 03:37 5,120 System.Globalization.dll
2016/06/20 下午 03:37 5,120 System.IO.dll
2016/06/20 下午 03:37 5,632 System.Linq.dll
2016/06/20 下午 03:37 7,168 System.Linq.Expressions.dll
2016/06/20 下午 03:37 4,608 System.Linq.Queryable.dll
2016/06/20 下午 03:37 122,368 System.Net.Http.dll
2016/06/20 下午 03:36 48,067 System.Net.Http.dll.mdb
2015/02/19 下午 08:10 22,232 System.Net.Http.Extensions.dll
2015/02/19 下午 08:10 21,720 System.Net.Http.Primitives.dll
2016/06/20 下午 03:37 5,632 System.Net.Primitives.dll
2016/06/20 下午 03:37 5,632 System.ObjectModel.dll
2016/06/20 下午 03:37 5,632 System.Reflection.dll
2016/06/20 下午 03:37 4,608 System.Reflection.Extensions.dll
2016/06/20 下午 03:37 4,608 System.Resources.ResourceManager.dll
2016/06/20 下午 03:37 13,824 System.Runtime.dll
2016/06/20 下午 03:37 5,120 System.Runtime.Extensions.dll
2016/06/20 下午 03:37 6,144 System.Runtime.InteropServices.dll
2016/06/20 下午 03:37 889,856 System.Runtime.Serialization.dll
2016/06/20 下午 03:36 322,073 System.Runtime.Serialization.dll.mdb
2016/06/20 下午 03:37 5,120 System.Runtime.Serialization.Primitives.dll
2016/06/20 下午 03:37 227,840 System.ServiceModel.Internals.dll
2016/06/20 下午 03:36 89,254 System.ServiceModel.Internals.dll.mdb
2016/06/20 下午 03:37 5,120 System.Text.Encoding.dll
2016/06/20 下午 03:37 4,608 System.Text.Encoding.Extensions.dll
2016/06/20 下午 03:37 4,608 System.Text.RegularExpressions.dll
2016/06/20 下午 03:37 5,632 System.Threading.dll
2016/06/20 下午 03:37 6,656 System.Threading.Tasks.dll
2016/06/20 下午 03:37 2,432,512 System.Xml.dll
2016/06/20 下午 03:36 953,244 System.Xml.dll.mdb
2016/06/20 下午 03:37 133,632 System.Xml.Linq.dll
2016/06/20 下午 03:36 50,083 System.Xml.Linq.dll.mdb
2016/06/20 下午 03:37 6,656 System.Xml.ReaderWriter.dll
2016/06/20 下午 03:37 6,144 System.Xml.XDocument.dll
2048/11/30 上午 05:06 286,208 Xamarin.Android.Support.Design.dll
1980/01/01 上午 12:00 1,872,384 Xamarin.Android.Support.v4.dll
2047/01/23 下午 07:30 953,856 Xamarin.Android.Support.v7.AppCompat.dll
2047/10/19 上午 12:34 33,792 Xamarin.Android.Support.v7.CardView.dll
2047/07/28 下午 03:19 198,144 Xamarin.Android.Support.v7.MediaRouter.dll
2016/01/18 下午 03:36 426,496 Xamarin.Forms.Core.dll
2016/01/18 下午 03:36 230,400 Xamarin.Forms.Platform.Android.dll
2016/01/18 下午 03:36 71,168 Xamarin.Forms.Platform.dll
2016/01/18 下午 03:36 61,440 Xamarin.Forms.Xaml.dll
Sdk Assemblies Only
2016/07/29 下午 10:08 22,016 DoggyMobileBE.dll
2016/07/29 下午 10:08 931 DoggyMobileBE.dll.config
2016/07/29 下午 10:08 3,713 DoggyMobileBE.dll.mdb
2016/07/29 下午 10:08 90,112 DoggyMobileBE.Droid.dll
2016/07/29 下午 10:08 9,078 DoggyMobileBE.Droid.dll.mdb
2016/07/29 下午 10:08 11,776 FormsViewGroup.dll
2016/07/29 下午 10:08 92,672 Java.Interop.dll
2016/07/29 下午 10:08 34,533 Java.Interop.dll.mdb
2016/06/20 下午 03:37 30,720 Microsoft.CSharp.dll
2016/07/29 下午 10:08 327,168 Microsoft.WindowsAzure.Mobile.dll
2016/07/29 下午 10:08 84,992 Microsoft.WindowsAzure.Mobile.Ext.dll
2016/07/29 下午 10:08 1,532,928 Mono.Android.dll
2016/06/20 下午 03:37 1,350,144 Mono.CSharp.dll
2016/07/29 下午 10:08 2,186,752 mscorlib.dll
2016/07/29 下午 10:08 446,464 Newtonsoft.Json.dll
2016/06/20 下午 03:37 869,376 System.Core.dll
2016/07/29 下午 10:08 665,600 System.dll
2016/07/29 下午 10:08 83,456 System.Net.Http.dll
2016/07/29 下午 10:08 5,632 System.Net.Http.Extensions.dll
2016/07/29 下午 10:08 5,120 System.Net.Http.Primitives.dll
2016/07/29 下午 10:08 442,368 System.Runtime.Serialization.dll
2016/06/20 下午 03:37 227,840 System.ServiceModel.Internals.dll
2016/07/29 下午 10:07 89,254 System.ServiceModel.Internals.dll.mdb
2016/07/29 下午 10:08 1,052,672 System.Xml.dll
2016/07/29 下午 10:08 46,080 System.Xml.Linq.dll
2048/11/30 上午 05:06 286,208 Xamarin.Android.Support.Design.dll
1980/01/01 上午 12:00 1,872,384 Xamarin.Android.Support.v4.dll
2047/01/23 下午 07:30 953,856 Xamarin.Android.Support.v7.AppCompat.dll
2047/10/19 上午 12:34 33,792 Xamarin.Android.Support.v7.CardView.dll
2047/07/28 下午 03:19 198,144 Xamarin.Android.Support.v7.MediaRouter.dll
2016/07/29 下午 10:08 465,408 Xamarin.Forms.Core.dll
2016/07/29 下午 10:08 235,520 Xamarin.Forms.Platform.Android.dll
2016/07/29 下午 10:08 78,848 Xamarin.Forms.Platform.dll
2016/07/29 下午 10:08 63,488 Xamarin.Forms.Xaml.dll
Sdk and User Assemblies
2016/07/29 下午 10:10 14,336 DoggyMobileBE.dll
2016/07/29 下午 10:10 931 DoggyMobileBE.dll.config
2016/07/29 下午 10:10 2,362 DoggyMobileBE.dll.mdb
2016/07/29 下午 10:10 90,112 DoggyMobileBE.Droid.dll
2016/07/29 下午 10:10 9,078 DoggyMobileBE.Droid.dll.mdb
2016/07/29 下午 10:10 11,776 FormsViewGroup.dll
2016/07/29 下午 10:10 92,160 Java.Interop.dll
2016/07/29 下午 10:10 34,308 Java.Interop.dll.mdb
2016/06/20 下午 03:37 30,720 Microsoft.CSharp.dll
2016/07/29 下午 10:10 120,320 Microsoft.WindowsAzure.Mobile.dll
2016/07/29 下午 10:10 84,992 Microsoft.WindowsAzure.Mobile.Ext.dll
2016/07/29 下午 10:10 1,338,368 Mono.Android.dll
2016/06/20 下午 03:37 1,350,144 Mono.CSharp.dll
2016/07/29 下午 10:10 2,177,024 mscorlib.dll
2016/07/29 下午 10:10 310,784 Newtonsoft.Json.dll
2016/06/20 下午 03:37 869,376 System.Core.dll
2016/07/29 下午 10:10 640,000 System.dll
2016/07/29 下午 10:10 83,456 System.Net.Http.dll
2016/07/29 下午 10:10 5,120 System.Net.Http.Extensions.dll
2016/07/29 下午 10:10 442,368 System.Runtime.Serialization.dll
2016/07/29 下午 10:10 58,368 System.ServiceModel.Internals.dll
2016/07/29 下午 10:10 14,321 System.ServiceModel.Internals.dll.mdb
2016/07/29 下午 10:10 1,052,672 System.Xml.dll
2016/07/29 下午 10:10 46,080 System.Xml.Linq.dll
2016/07/29 下午 10:10 40,960 Xamarin.Android.Support.Design.dll
2016/07/29 下午 10:10 369,664 Xamarin.Android.Support.v4.dll
2016/07/29 下午 10:10 402,944 Xamarin.Android.Support.v7.AppCompat.dll
2016/07/29 下午 10:10 25,088 Xamarin.Android.Support.v7.CardView.dll
2016/07/29 下午 10:10 5,632 Xamarin.Android.Support.v7.MediaRouter.dll
2016/07/29 下午 10:10 465,408 Xamarin.Forms.Core.dll
2016/07/29 下午 10:10 235,520 Xamarin.Forms.Platform.Android.dll
2016/07/29 下午 10:10 77,824 Xamarin.Forms.Platform.dll
2016/07/29 下午 10:10 63,488 Xamarin.Forms.Xaml.dll
解決因為 Linker 造成意外移除的問題
當在
Sdk and User Assemblies
Linker 模式下執行,會產生一個例外異常:
Xamarin.Forms.Xaml.XamlParseException: Position 29:19. No method OnAdd found on type DoggyMobileBE.TodoList
要解決這樣的問題有底下方法:
- 採用
None
的模式來進行Linker
處理,不過,這樣產生的 APK 檔案室會相當大的。 - 使用
Sdk Assemblies Only
的模式來進行Linker
處理,也就是說,Linker 僅會將 來自於 Xamarin.Android 的組件進行 Linker 靜態分析,並且移除掉沒有用到的組件、型別或者成員,而其他的組件就不會進行 Linker 處理。 - 若您一定想要使用
Sdk and User Assemblies
Linker 模式,您需要逐步將意外被 Linker 移除的組件內容,把他強制加回來。
明確指名不要 Linker 的組件
這個方法比較適合用於您沒有原始碼組件,例如,使用 NuGet 加入的套件。
- 請在設定 Linker 的同一個標籤頁面
- 在
Skip linking assemblies
標題下方,將核心 PCL 的組件加入到這個欄位內,告知 Linker 要排除這個組件,不要做任何連結分析的處理行為。 - 接著,再度執行程式,詳細執行您應用程式的每個地方,看看有那些地方還是會產生例外異常的閃退行為,找出其所屬的組件,回到步驟 2
- 持續處理,直到沒有發生任何例外異常的閃退行為。
使用 Android.Runtime.Preserve 從 Linker 中排除
- 底下為將 Example 這個類別的建構式從 Linker 中排除
public class Example
{
[Android.Runtime.Preserve]
public Example ()
{
}
}
- 底下為要保留整個類別,不要在 Linker
[Android.Runtime.Preserve (AllMembers = true)]
class Example
{
// Compiler provides default constructor...
}
使用自訂 Linker 的設定檔案
您可以產生一個 XML 內容的檔案,加入到原生專案內,不過,對於不同原生專案,需要做不同的設定
- Xamarin.Android
建置動作
需要指定LinkDescription
- Xamarin.iOS請把這個文字
--xml=FILE
在 mtouch 引數內 - 底下為一個 XML 範例
<linker>
<assembly fullname="mscorlib">
<type fullname="System.Environment">
<field name="mono_corlib_version" />
<method name="get_StackTrace" />
</type>
</assembly>
<assembly fullname="My.Own.Assembly">
<type fullname="Foo" preserve="fields">
<method name=".ctor" />
</type>
<type fullname="Bar">
<method signature="System.Void .ctor(System.String)" />
<field signature="System.String _blah" />
</type>
<namespace fullname="My.Own.Namespace" />
<type fullname="My.Other*" />
</assembly>
</linker>
靜態分析
決定出哪個組件(Assembley)實際上是有被使用、哪個型別(Type)實際上是有被使用並且哪個成員(Member)實際上有被使用。Linker
的分析過程類似 CRL(Common Runtime Library) 的垃圾回收 (Garbage Collector) 處理方式,會持續地尋找組件、類型、成員,看看這些元素是否有被參考到;最後,將沒有參考的元素,將會被Linker
忽略掉,也就是不會產生在 APK 檔案裡面。