虽然每个方法都被定义为返回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,领红包你赚我也赚。