Xamarin.Forms引用System.ObjectModel程序集Android端崩溃问题
Xamarin.Forms XAML中ObservableCollection跨平台运行异常解决方案
问题根因
不同平台运行时对System.Collections.ObjectModel.ObservableCollection的类型承载程序集有差异:
- iOS、UWP平台旧版运行时中,该类型实现在
System.ObjectModel程序集内 - Android平台Mono运行时、.NET Standard适配层中,该类型通过
netstandard程序集做类型转发
在XAML命名空间声明中硬编码固定的assembly属性,会导致对应平台找不到目标类型触发运行时崩溃。额外安装System.ObjectModel NuGet包无效的原因是,Xamarin.Forms各平台项目已内置对应版本的该程序集,额外安装的独立包会和内置版本产生冲突,无法解决类型定位问题。
可行解决方案
方案1:移除命名空间声明中的硬编码程序集属性(优先推荐)
修改XAML头部的命名空间声明,去掉assembly配置段,让XAML解析器自动在当前项目所有已引用程序集中查找对应类型,自动适配各平台的类型加载规则:
xmlns:col="clr-namespace:System.Collections.ObjectModel"
该写法不需要做其他适配,绝大多数场景下可以直接解决跨平台类型加载问题。
方案2:通过OnPlatform做平台差异化资源声明
如果移除assembly属性后仍存在类型解析问题,可以利用Xamarin.Forms内置的OnPlatform标记,为不同平台声明对应程序集的集合资源:
<ResourceDictionary> <OnPlatform x:Key="NewTabs" x:TypeArguments="col:ObservableCollection(model:ISequenceItem)"> <On Platform="iOS, UWP"> <On.Value> <col:ObservableCollection x:TypeArguments="model:ISequenceItem" xmlns:col="clr-namespace:System.Collections.ObjectModel;assembly=System.ObjectModel"> <test:FirstPage Order="1" Text="Page 1" /> <test:SecondPage Order="2" Text="Page 2" /> <test:ThirdPage Order="3" Text="Page 3" /> </col:ObservableCollection> </On.Value> </On> <On Platform="Android"> <On.Value> <col:ObservableCollection x:TypeArguments="model:ISequenceItem" xmlns:col="clr-namespace:System.Collections.ObjectModel;assembly=netstandard"> <test:FirstPage Order="1" Text="Page 1" /> <test:SecondPage Order="2" Text="Page 2" /> <test:ThirdPage Order="3" Text="Page 3" /> </col:ObservableCollection> </On.Value> </On> </OnPlatform> </ResourceDictionary> <test:Tabs ItemsSource="{Binding Path=NewTabs}" SelectedItem="{Binding Path=SelectedTab}">
方案3:将集合定义迁移至代码层(稳定性最高)
标签页数据源属于视图逻辑范畴,直接在页面对应的ViewModel或代码后置中实例化集合,完全绕开XAML解析器的类型加载差异,同时符合MVVM开发规范:
// ViewModel 或 页面代码后置中定义 public ObservableCollection<ISequenceItem> NewTabs { get; } = new ObservableCollection<ISequenceItem>() { new FirstPage { Order = 1, Text = "Page 1" }, new SecondPage { Order = 2, Text = "Page 2" }, new ThirdPage { Order = 3, Text = "Page 3" } };
XAML中直接绑定该属性即可,不需要在资源字典中声明XAML实例化的集合,该写法不存在任何跨平台类型加载兼容问题。
内容的提问来源于stack exchange,提问作者Mannu
相关产品推荐
相关产品推荐

