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

简介: 虽然每个方法都被定义为返回Task或Task 对象,但是方法的主体没有任何对Task或Task 的引用。相反,返回Task对象的方法只是执行一些工作,然后使用隐式return语句结束该方法。 ExistsAsync方法定义为返回Task 但返回true或false。

虽然每个方法都被定义为返回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();
        __
    }
}

好久没更新系列博客了,对不起大家了。今天接着来。大家要是喜欢,支持一下,打开你的支付宝,搜索栏输入9654711,领红包你赚我也赚。

目录
相关文章
|
Web App开发 Android开发
第二十章:异步和文件I/O.(二十三)
回到网上在本章之前,本书中唯一的异步代码涉及使用可移植类库WebRequest中唯一可用于此目的的合理类进行Web访问。 WebRequest类使用称为异步编程模型或APM的旧异步协议。 APM涉及两种方法,在WebRequest的情况下,这些方法称为BeginGetResponse和EndGetResponse。
716 0