Xamarin.Form目前是微軟提供的一種跨平臺的開發技術,可以讓開發者在iOS、Android和Window Phone等平臺上共享60%以上的代碼,從而節省維護多個平臺代碼的精力。但是完全不跟特定平臺的代碼打交道也是不可能的,為此,Xamarin.Form提供了一個強大的Api,讓開發者可以實現跨平臺調用代碼,這個Api就是DependencyService。
利用DependencyService,我們就可以調用特定平臺的代碼,從而可以做原生代碼所能做的任何事情。
為了在Xamarin.Form中使用DependencyService,我們需要做以下四件事情。
- 定義接口,這個接口是平臺無關的,定義了Xamarin.Form與特定平臺交互的方式。
- 編寫特定平臺上的具體實現。
- 通過DependencyService所提供的元標記來注冊這些實現,讓DependencyService在運行時可以找到特定的實現類。
- 在Xamarin.Form中使用DependencyService顯式調用接口的實現。
定義接口
接口決定了我們在Xamarin.Form中使用平臺代碼的方式,這里我們定義一個文本轉語音的接口。
public interface ITextToSpeech {
void Speak ( string text );
}
編寫特定平臺上的實現
實現類必然要實現上面所定義的接口,并且必須有一個無參構造器。
這里以iOS平臺為例。
public class TextToSpeechImplementation : ITextToSpeech
{
public TextToSpeechImplementation () {}
public void Speak (string text)
{
var speechSynthesizer = new AVSpeechSynthesizer ();
var speechUtterance = new AVSpeechUtterance (text) {
Rate = AVSpeechUtterance.MaximumSpeechRate/4,
Voice = AVSpeechSynthesisVoice.FromLanguage ("en-US"),
Volume = 0.5f,
PitchMultiplier = 1.0f
};
speechSynthesizer.SpeakUtterance (speechUtterance);
}
}
注冊實現
完成實現之后,我們還要使用[assembly]
標記來注冊他們,唯有這樣,DependencyService才能在運行時找到接口所對應的實現類。
我們要在命名空間之上添加如下代碼:
using AVFoundation;
using DependencyServiceSample.iOS;//enables registration outside of namespace
[assembly: Xamarin.Forms.Dependency (typeof (TextToSpeechImplementation))]
namespace DependencyServiceSample.iOS {
public class TextToSpeechImplementation : ITextToSpeech
......
其中,由于注冊的聲明位置在命名空間之外,所以需要在引用中添加對該命名空間的引用,否則注冊會報錯。
將上述兩部分加在一起的實現類完整代碼如下:
using AVFoundation;
using DependencyServiceSample.iOS;//enables registration outside of namespace
[assembly: Xamarin.Forms.Dependency (typeof (TextToSpeechImplementation))]
namespace DependencyServiceSample.iOS {
public class TextToSpeechImplementation : ITextToSpeech
{
public TextToSpeechImplementation () {}
public void Speak (string text)
{
var speechSynthesizer = new AVSpeechSynthesizer ();
var speechUtterance = new AVSpeechUtterance (text) {
Rate = AVSpeechUtterance.MaximumSpeechRate/4,
Voice = AVSpeechSynthesisVoice.FromLanguage ("en-US"),
Volume = 0.5f,
PitchMultiplier = 1.0f
};
speechSynthesizer.SpeakUtterance (speechUtterance);
}
}
在Android平臺和Window Phone上也是如此,除了實現不同,其它的部分都是一樣的。這里不作贅述。
使用DependencyService
完成了上述步驟之后,我們在Xamarin.Form使用DependencyService.Get<ITextToSpeech>()
就可以獲得一個ITextToSpeech實現類的實例對象。
具體獲得哪一個實現類取決于Xamarin.Form所運行的平臺。
需要指出的是,DependencyService.Get<T>()
每一次都會返回同一個對象,事實上,Get<T>()
是這樣的:Get<T>(DependencyFetchTarget)
。
DependencyFetchTarget是個枚舉類,
public enum DependencyFetchTarget
{
GlobalInstance,
NewInstance
}
故名思義,GlobalInstance
是每次都返回同一個全局的對象,也就單例模式;而NewInstance
則是每次都返回一個新的對象。而Get<T>()
等價于Get<T>(DependencyFetchTarget.GlobalInstance)
,因此默認是單例模式。
可以看出,DependencyService.Get<T>()
是不接收其它參數類型的,這也就是為什么實現類必須有一個無參構造器。
最后,代碼結構應該如下這般: