介绍
本编文章分为2节,第1节是介绍项目中遇到的业务场景问题,第2节是分析以及解决该业务场景问题的方法。
Part 1 业务场景中遇到的问题
本次文章中使用的Github的一个Xamarin.Forms的代码Demo是 abdulrahmanelfeky/SkiaPulse-Xamarin.Forms ,作者使用SkiaSharp完成了一个在Forms中调用XAML界面控件 ,就能在Android与iOS中显示一个律动界面控件的效果。
在尝试将这个Demo写成 .Net Standard 类库时遇到了几个问题。当我将该Demo中的核心业务逻辑的Pulse.cs文件放到 .Net Standard 中成功编译并在另一个新建的空项目中运行时,律动的效果正常地出现了,但是在XAML指定了的图片却没有出现。
Part 2 问题的分析及解决方法
XAML中涉及到图片的显示是Source属性
<SkiaPulse:Pulse Source="SkiaPulse.Images.wifi_icon.png" AutoStart="true" PulseColor="#8e44ad" Margin="50" Speed="10"/>
而源码中的OnPropertyChanged函数内含有处理Source属性的业务逻辑
if (propertyName == nameof(Source))
{
string resourceID = Source;
Assembly assembly = GetType().GetTypeInfo().Assembly;
using (Stream stream = assembly.GetManifestResourceStream(resourceID))
{
if (stream != null)
resourceBitmap = SKBitmap.Decode(stream);
}
resourceBitmap = resourceBitmap?.Resize(new SKImageInfo(90, 90), SKFilterQuality.Medium);
}
而图片的数据会以二进制格式存到Stream中,所以一开始我的思路是直接使用Forms提供的 Embedded images 来获取图片的Stream数据。
ImageSource.FromResource 函数返回的结果是一个 StreamImageSource 类型,其中就包含了名为 Stream 的属性,但是该属性是一个 Func 类型,当我调用该属性的Invoke函数时,结果得到的却是Null。
而官方在Xamarin论坛上说过其实Xamarin中无法从ImageSouce得到图片的Stream。
重新整理一下调用的思路,如图:
回到作者的源码中,结合两行代码分析:
Assembly assembly = GetType().GetTypeInfo().Assembly;//运行时获得本程序集
Stream stream = assembly.GetManifestResourceStream(resourceID)//从本程序集通过资源ID获得Stream
在程序运行的时候,Assembly assembly = GetType().GetTypeInfo().Assembly;获取到的程序集是图中的左边第一个DLL,而图片是在做业务开发的时候添加到图中中间的Forms DLL中,所以Stream stream = assembly.GetManifestResourceStream(resourceID)是无法获取到图片的数据的。
那我们需要怎样在图中左边第一个DLL中获取到图中中间DLL的图片呢?传参。
回到微软的Xamarin文档 Embedded images 中看到
In this example the resource ID is WorkingWithImages.beach.jpg.
The IDE has generated this default by concatenating the Default Namespace for this project with the filename,
using a period (.) between each value.
我们在做业务开发时添加到Forms层的图片名称,含有命名空间(Namespace)。
而有了命名空间,就可以通过反射,获取到该命名空间的程序集相关信息。
通过 . 符号对参数resourceID进行分割后,数组中的第0个数据就是我们程序集的名字。
这时候通过Assembly的 Load 函数加载出Forms DLL的程序集就可以获取到图片数据了。
原作者 App 代码参看:
abdulrahmanelfeky/SkiaPulse-Xamarin.Forms
调用Nuget的代码参看:
jingliancui/XamarinFormsSkiaPulseSample
Nuget包:
Install-Package XamarinLibrary.Xamarin.Forms.SkiaPulse -Version 1.0.0
微信公众号 :
Xamarin Library
QQ群:
313308215