Linker设定:程序代码优化
|
不论是在Android或iOS的项目中,项目属性内都有一个Linker选项,例如下图:
Linker设定指的就是程序代码的优化,
所谓的优化就是在编译程序代码时仅编译出有使用到的对象、方法、属性及事件等,
每个选项的编译行为如下:
None 或Dont link:不进行任何的优化,通常在需要进行DeBug时或特殊需求才会选此项。
SDK Assemblies only:对Xamarin.Android 或 Xamarin.iOS的做优化 All Assemblies:最所有组件优化。
默认在DeBug模式下使用None,
Release模式下默认是SDK Assemblies only,
以Android为例,从编译出的apk档的大小可以看出很明显的差异。
使用None编译出的大小约26MB:
使用SDK Assemblies only编译出的大小约3.4MB:
因此在撰写程序代码时, 应尽量避免使用到反射的写法, 如下程序代码使用了反射的方式更改了Button的文字,使用None模式时一切正常
1 | Button button = FindViewById<Button>(Resource.Id.MyButton); |
2 | typeof (Button).GetProperty( "Text" ).SetValue(button, "test Linker" ); |
但改成SDK Assemblies only后,执行立刻就报错了
错误为NullReferenceException,因为GetProperty("Text")找不到名称为Text的属性回传了Null。
那怎样的情况这个属性才会被编译?需要出现如下代码段:
1 | button.Text = "test" ; |
虽然上面的程序代码会让Text属性被编译进去, 但也只编译了Set的部分,如果用反射去Get照样会死给你看...
但如果还是得需要用到反射, 我们可以自行定义XML档案指定编译时省略哪些东西不做优化处理。 以上方的程序代码来说,我们希望Button的Text不要被优化, 而Text属性又是继承了TextView而来:
所以这里要处理的其实是Android.Widget.TextView, 而由上方的组件信息可得知组件名称
接着就可以在项目中加入Xml,并撰写以下内容:
1 | < linker > |
2 | < assembly fullname = "Mono.Android" > |
3 | < type fullname = "Android.Widget.TextView" ></ type > |
4 | </ assembly > |
5 | </ linker > |
assembly fullname放的就是组件名称,
type fullname里放的就是要省略优化类别名(要含NameSpace)。
接着在Android中,选择该Xml档案,
在建置动作的地方选择LinkDescription,并且重新建置项目。
如果是在iOS下,依照同样的方法取得组件名称与类别完整名称后,
一样建立Xml在项目目录下并撰写相同格式内容XML,
最后在项目属性内iOS Build→于Additional mtouch arguments输入(linker为自建目录):
--xml=${ProjectDir}/linker/setting.xml 如图
这样就可以避免程序优化导致反射无法使用,
但相对的会增加一点点编译出的程序大小(可能1~2K之类的)。
其他当然还是有方法可以避免被优化,
但要调整SDK的优化只能用此方式喔。
作者:Steven Chang 2015/04 |
链接:http://www.thinkpower.info/xamarin/cn/Article_19.aspx?idx=19#xamarin_top