雖然每個方法都被定義爲返回Task或Task 對象,但是方法的主體沒有任何對Task或Task 的引用。相反,返回Task對象的方法只是執行一些工作,然後使用隱式return語句結束該方法。 ExistsAsync方法定義爲返回Task 但返回true或false。 (StorageFolder類中沒有Exists方法,因此需要使用try和catch進行解決方法。)
類似地,ReadTextAsync方法被定義爲返回Task ,但是body返回一個字符串,該字符串是通過將await運算符應用於File.ReadTextAsync的IAsyncOperation 返回值而獲得的。 C#編譯器執行必要的轉換。
當程序調用此ReadTextAsync方法時,該方法將執行,直到第一個await運算符,然後它將一個Task 對象返回給調用者。當FileIO.ReadTextAsync方法完成時,調用者可以使用ContinueWith或await來獲取字符串。
但是,對於iOS和Android,我們現在遇到了問題。現在,IFileHelper中的所有方法都被定義爲返回Task或Task 對象的異步方法,但我們已經看到System.IO命名空間中的方法不是異步的。我們做什麼?
iOS命名空間中的FileHelper類使用兩種策略。 在某些情況下,System.IO類確實包含異步方法。 Stream Writer的WriteAsync方法和StreamReader的ReadAsync方法就是這種情況。 但是,對於其他方法,使用Task 的靜態FromResult方法將對象或值轉換爲Task 對象以獲取方法返回值。 這實際上並不是將方法轉換爲異步方法,而只是允許方法具有同步方法的簽名:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Xamarin.Forms;
[assembly: Dependency(typeof(Xamarin.FormsBook.Platform.iOS.FileHelper))]
namespace Xamarin.FormsBook.Platform.iOS
{
class FileHelper : IFileHelper
{
public Task<bool> ExistsAsync(string filename)
{
string filepath = GetFilePath(filename);
bool exists = File.Exists(filepath);
return Task<bool>.FromResult(exists);
}
public async Task WriteTextAsync(string filename, string text)
{
string filepath = GetFilePath(filename);
using (StreamWriter writer = File.CreateText(filepath))
{
await writer.WriteAsync(text);
}
}
public async Task<string> ReadTextAsync(string filename)
{
string filepath = GetFilePath(filename);
using (StreamReader reader = File.OpenText(filepath))
{
return await reader.ReadToEndAsync();
}
}
public Task<IEnumerable<string>> GetFilesAsync()
{
// Sort the filenames.
IEnumerable<string> filenames =
from filepath in Directory.EnumerateFiles(GetDocsFolder())
select Path.GetFileName(filepath);
return Task<IEnumerable<string>>.FromResult(filenames);
}
public Task DeleteAsync(string filename)
{
File.Delete(GetFilePath(filename));
return Task.FromResult(true);
}
string GetDocsFolder()
{
return Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
}
string GetFilePath(string filename)
{
return Path.Combine(GetDocsFolder(), filename);
}
}
}
Android FileHelper類與iOS類相同,但具有不同的命名空間。
請注意,這些平臺實現中唯一的錯誤檢查是Windows運行時平臺中的ExistsAsync方法,它使用異常來確定文件是否存在。 沒有其他方法 - 特別是WriteTextAsync和ReadTextAsync
方法 - 正在執行任何錯誤檢查。 使用await的一個很好的功能是,當你實際調用這些方法時,可以在以後捕獲任何異常。
您可能還注意到,各個GetFilesAsync方法現在正在從完全限定的文件名中刪除路徑,因此該作業不需要由Xamarin.FormsBook.Platform項目中的FileHelper類執行:
namespace Xamarin.FormsBook.Platform
{
class FileHelper
{
IFileHelper fileHelper = DependencyService.Get<IFileHelper>();
public Task<bool> ExistsAsync(string filename)
{
return fileHelper.ExistsAsync(filename);
}
public Task WriteTextAsync(string filename, string text)
{
return fileHelper.WriteTextAsync(filename, text);
}
public Task<string> ReadTextAsync(string filename)
{
return fileHelper.ReadTextAsync(filename);
}
public Task<IEnumerable<string>> GetFilesAsync()
{
return fileHelper.GetFilesAsync();
}
public Task DeleteAsync(string filename)
{
return fileHelper.DeleteAsync(filename);
}
}
}
現在我們有了一個庫,我們需要從一個應用程序訪問這個庫。 TextFileAsync解決方案是正常創建的。 然後,Xamarin.FormsBook.Platform解決方案中的所有七個項目都添加到此解決方案中。 必須使用解決方案的“添加和現有項目”菜單項單獨添加這些項目。 解決方案菜單項中沒有添加所有項目,但如果您在自己的項目中使用這些庫,您會希望有!
此時,TextFileAsync解決方案包含13個項目:五個應用程序項目,一個包含應用程序代碼的共享PCL和七個庫項目。
必須使用Reference Manager爲以下關係在這些項目之間建立引用:
- TextFileAsync引用了Xamarin.FormsBook.Platform。
- TextFileAsync.iOS引用了Xamarin.FormsBook.Platform.iOS。
- TextFileAsync.Droid引用了Xamarin.FormsBook.Platform.Android。
- TextFileAsync.UWP引用了Xamarin.FormsBook.Platform.UWP。
- TextFileAsync.Windows引用了Xamarin.FormsBook.Platform.Windows。
- TextFileAsync.WinPhone引用了Xamarin.FormsBook.Platform.WinPhone。
當然,所有應用程序項目都有對TextFileAsync PCL的正常引用,並且,正如您所記得的,Xamarin.FormsBook.Platform.UWP,Windows和WinPhone項目都引用了共享的Xamarin.FormsBook.Platform.WinRT 項目。
此外,所有TextFileAsync項目都應該調用庫中的各種Toolkit.Init方法。 在TextFileAsync項目本身中,在App類的構造函數中進行調用:
namespace TextFileAsync
{
public class App : Application
{
public App()
{
Xamarin.FormsBook.Platform.Toolkit.Init();
__
}
__
}
}
在iOS項目中,在AppDelegate類中正常的Forms.Init調用之後進行調用:
namespace TextFileAsync.iOS
{
__
public partial class AppDelegate :
global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
__
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
Xamarin.FormsBook.Platform.iOS.Toolkit.Init();
LoadApplication(new App());
__
}
}
}
在Android項目中,在正常的Forms.Init調用之後,使用MainActivity類中的MainActivity和Bundle對象調用Toolkit.Init:
namespace TextFileAsync.Droid
{
__
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
{
protected override void OnCreate(Bundle bundle)
{
__
global::Xamarin.Forms.Forms.Init(this, bundle);
Xamarin.FormsBook.Platform.Android.Toolkit.Init(this, bundle);
LoadApplication(new App());
}
}
}
在Windows平臺中,在App.xaml.cs文件中的Forms.Init之後立即調用Toolkit.Init:
namespace TextFileAsync.UWP
{
__
sealed partial class App : Application
{
__
Xamarin.Forms.Forms.Init(e);
Xamarin.FormsBook.Platform.UWP.Toolkit.Init();
__
}
}
好久沒更新系列博客了,對不起大家了。今天接着來。大家要是喜歡,支持一下