特定於平臺的庫
每個程序員都知道應該將可重用的代碼放在庫中,對於依賴服務使用的代碼也是如此。這裏開發的異步文件I / O函數將在第24章的NoteTaker程序中重用,您可能希望在自己的應用程序中使用這些函數,或者開發自己的函數。
但是,這些文件I / O類不能只放在一個庫中。 FileHelper的各種平臺實現必須位於該特定平臺的庫中。這需要爲每個平臺分別創建庫。
本書可下載代碼的Libraries目錄包含一個名爲Xamarin.FormsBook.Platform的解決方案。該名稱的平臺部分受到各種Xamarin.Forms.Platform庫的啓發。各種平臺中的每一個都是此解決方案中的獨立庫。
Xamarin.FormsBook.Platform解決方案包含不少於七個庫項目,每個項目的創建方式都有所不同:
- Xamarin.FormsBook.Platform是一個普通的Xamarin.Forms可移植類庫,其配置文件爲111,這意味着它可以被所有平臺訪問。 您可以通過選擇“添加新項目”對話框左側的“交叉平臺”和中心區域中的“類庫(Xamarin.Forms)”,在Visual Studio中創建此類庫。 在Xamarin Studio New Project對話框中,選擇左側的Multiplatform和Library,以及中心區域的Xamarin.Forms和Class Library。
- Xamarin.FormsBook.Platform.iOS是在Visual Studio中創建的,方法是在“添加新項目”對話框的左欄中選擇iOS,在中央部分選擇“類庫”(iOS)。在Xamarin Studio中,在New Project對話框中選擇iOS和Library,在中心區域選擇Class Library。
- Xamarin.FormsBook.Platform.Android是在Visual Studio中創建的,方法是在“添加新項目”對話框的左側選擇Android,在中央部分選擇“類庫”(Android)。在Xamarin.Studio中,選擇左側的Android和Library以及中央部分的Class Library。
- Xamarin.FormsBook.Platform.UWP是適用於Windows 10和Windows 10 Mobile的庫。它是在Visual Studio中通過選擇左側的Windows和Universal,然後選擇類庫(通用Windows)創建的。
- Xamarin.FormsBook.Platform.Windows是一個適用於Windows 8.1的可移植類庫。它是在Visual Studio中通過選擇左側的Windows,Windows 8和Windows,然後選擇類庫(Windows 8.1)創建的。
- Xamarin.FormsBook.Platform.WinPhone是一個適用於Windows Phone 8.1的可移植類庫。它是在Visual Studio中通過選擇左側的Windows,Windows 8和Windows Phone,然後選擇類庫(Windows Phone)創建的。
- 您經常會發現三個Windows平臺可以共享代碼,因爲它們都使用Windows運行時API的變體。出於這個原因,創建了第七個項目名爲Xamarin.FormsBook.Platform.WinRT。這是一個共享項目,它是在Visual Studio中通過在“添加新項目”對話框中搜索“共享”,併爲C#選擇共享項目而創建的。
如果您自己創建這樣的解決方案,則還需要使用Manage Packages for Solution對話框爲所有這些庫安裝相應的Xamarin.Forms NuGet包。
您還需要在解決方案中的各個項目之間建立引用。 所有單個平臺項目(Xamarin.FormsBook.Platform.WinRT除外)都需要引用Xamarin.FormsBook.Platform。 您可以通過選擇左側的Solution在Reference Manager對話框中設置這些引用。 此外,三個Windows項目(UWP,Windows和WinPhone)都需要引用共享的Xamarin.FormsBook.Platform.WinRT項目。 通過選擇左側的“共享項目”,可以在“參考管理器”對話框中設置這些引用
所有項目都有一個靜態的Toolkit.Init方法。 這是Xamarin.Forms中的一個?Book.Platform庫:
namespace Xamarin.FormsBook.Platform
{
public static class Toolkit
{
public static void Init()
{
}
}
}
除了Android庫中的版本實際上保存了一些可能對此庫中實現的類有用的信息之外,其他大多數都是相似的:
namespace Xamarin.FormsBook.Platform.Android
{
public static class Toolkit
{
public static void Init(Activity activity, Bundle bundle)
{
Activity = activity;
}
public static Activity Activity { private set; get; }
}
}
每個Windows平臺中的Toolkit.Init方法都調用do-nothing Toolkit.Init
共享Xamarin.FormsBook.Platform.WinRT項目中的方法:
namespace Xamarin.FormsBook.Platform.UWP
{
public static class Toolkit
{
public static void Init()
{
Xamarin.FormsBook.Platform.WinRT.Toolkit.Init();
}
}
}
這些方法的目的是確保庫綁定到應用程序,即使應用程序不直接訪問庫中的任何內容。 當您使用依賴服務和自定義渲染器時,應用程序不會直接調用任何庫函數。 但是,如果您稍後發現確實需要執行某些庫初始化,則此方法已存在。
您將發現本書可下載代碼中包含的Xamarin.FormsBook.Platform庫的版本已包含第9章“特定於平臺的API調用”中的PlatformSoundPlayer類。您還將看到一些以 單詞Ellipse和StepSlider。 這些將在第27章“自定義渲染器”中討論。
讓我們關注新的異步FileHelper類。 Xamarin.FormsBook.Platform庫包含新的IFileHelper接口:
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Xamarin.FormsBook.Platform
{
public interface IFileHelper
{
Task<bool> ExistsAsync(string filename);
Task WriteTextAsync(string filename, string text);
Task<string> ReadTextAsync(string filename);
Task<IEnumerable<string>> GetFilesAsync();
Task DeleteAsync(string filename);
}
}
按照慣例,返回Task對象的方法的後綴爲Async。
所有三個Windows平臺都可以共享相同的FileHelper類,因此這個共享類是在共享的Xamarin.FormsBook.Platform.WinRT項目中實現的。 FileHelper類中的五個方法中的每一個都以調用來開始,以獲取與應用程序的本地存儲區域關聯的StorageFolder。 它們中的每一個都使用await進行異步調用,並使用async關鍵字進行標記:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Windows.Storage;
using Xamarin.Forms;
[assembly: Dependency(typeof(Xamarin.FormsBook.Platform.WinRT.FileHelper))]
namespace Xamarin.FormsBook.Platform.WinRT
{
class FileHelper : IFileHelper
{
public async Task<bool> ExistsAsync(string filename)
{
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
try
{
await localFolder.GetFileAsync(filename);
}
catch
{
return false;
}
return true;
}
public async Task WriteTextAsync(string filename, string text)
{
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
IStorageFile storageFile = await localFolder.CreateFileAsync(filename,
CreationCollisionOption.ReplaceExisting);
await FileIO.WriteTextAsync(storageFile, text);
}
public async Task<string> ReadTextAsync(string filename)
{
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
IStorageFile storageFile = await localFolder.GetFileAsync(filename);
return await FileIO.ReadTextAsync(storageFile);
}
public async Task<IEnumerable<string>> GetFilesAsync()
{
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
IEnumerable<string> filenames =
from storageFile in await localFolder.GetFilesAsync()
select storageFile.Name;
return filenames;
}
public async Task DeleteAsync(string filename)
{
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
StorageFile storageFile = await localFolder.GetFileAsync(filename);
await storageFile.DeleteAsync();
}
}
}