1. 程式人生 > >第二十章:非同步和檔案I/O.(十二)

第二十章:非同步和檔案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();
        __
    }
}

好久沒更新系列部落格了,對不起大家了。今天接著來。大家要是喜歡,支援一下