第二十章:異步和文件I/O.(十二)

雖然每個方法都被定義爲返回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();
        __
    }
}

好久沒更新系列博客了,對不起大家了。今天接着來。大家要是喜歡,支持一下

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章